简介
Strconv 库是一些跨类型的转换函数集合,大家应该很熟悉。源码没有什么难点,主要是面试题有可能会出这种类型的,所以简单介绍下,主要介绍 以下两种常用转换,其他的没细研究,感兴趣的可以看看。
Strconv.Atoi 函数
将 字符串数组 转换为 数字,比较简单,源码如下
// Atoi 算法 核心思想 就是 每个字符 跟 ’0‘ 求差 然后迭代相加。因为面试可能会出这种题,可以借鉴下 整体不太难
func Atoi(s string) (int, error) {
const fnAtoi = "Atoi"
sLen := len(s)
if intSize == 32 && (0 < sLen && sLen < 10) || // intSize = 32 << (^uint(0) >> 63) 操作系统位数 ;如果是 32为操作系统,为 32<<0 32左移0位 还是 32,如果是64位 则 ^uint(0) >> 63==1 32左移1位就是64
intSize == 64 && (0 < sLen && sLen < 19) {
// Fast path for small integers that fit int type.
s0 := s // 这边之所以会复制一份 就是为了 将 对 s的处理 跟 输出 完整s信息和使用完整s进行一些判断 分开,使得逻辑简单。
if s[0] == '-' || s[0] == '+' { // 处理符号
s = s[1:]
if len(s) < 1 {
return 0, syntaxError(fnAtoi, s0)
}
}
n := 0
for _, ch := range []byte(s) { // 面试常考
ch -= '0'
if ch > 9 {
return 0, syntaxError(fnAtoi, s0)
}
n = n*10 + int(ch) // n 是每次迭代的结果
}
if s0[0] == '-' {
n = -n
}
return n, nil // 返回
}
// Slow path for invalid, big, or underscored integers.
i64, err := ParseInt(s, 10, 0) // 大数或者 无效整数走这里,感兴趣的可以看看
if nerr, ok := err.(*NumError); ok {
nerr.Func = fnAtoi
}
return int(i64), err
}
Strconv.Itoa 函数
Itoa 将 数字转换为字符串 其调用链如下
我们来看 formatBits 源码
// formatBits 执行逻辑:(只讲解10进制) 就是 将大数 %100 然后 再采取 在 smallsString映射的方法 查找 对应字符 再迭代。面试常考
func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { // base 进制 如果是 10 就对应 Itoa(i)
if base < 2 || base > len(digits) {
panic("strconv: illegal AppendInt/FormatInt base")
}
// 2 <= base && base <= len(digits)
var a [64 + 1]byte // +1 for sign of 64bit value in base 2 // 结果字节数组
i := len(a) // 长度 初始 为 65
if neg {
u = -u
}
// convert bits
// We use uint values where we can because those will
// fit into a single register even on a 32bit machine.
if base == 10 {
// common case: use constants for / because
// the compiler can optimize it into a multiply+shift
if host32bit { // 32位 操作系统 感兴趣的可以自己看看
// ...
}
// u guaranteed to fit into a uint
us := uint(u) // 转换成平台自适应 类型
for us >= 100 {
is := us % 100 * 2 // is 是 在 smallString 提取的起始索引
us /= 100 // us是下次扫描数据
i -= 2 // 一次可以获取两个
a[i+1] = smallsString[is+1]
a[i+0] = smallsString[is+0]
}
// us < 100
is := us * 2 // 走到这里 小于 100了
i-- // 更新 值
a[i] = smallsString[is+1] // 输出结果
if us >= 10 { // 小于10 就只有上面结果 大于10 则还需要输出 smallsString[is]
i--
a[i] = smallsString[is]
}
} else if isPowerOfTwo(base) { // 是 二进制 走这里
// ...
}
// add sign, if any
if neg { // 如果是负值 则 在前面加 -
i--
a[i] = '-'
}
if append_ { // true 返回 byte数组
d = append(dst, a[i:]...)
return
}
s = string(a[i:]) // 返回字符串
return
}