• Go源码--Strconv库


    简介

    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
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    Strconv.Itoa 函数

    Itoa 将 数字转换为字符串 其调用链如下
    ](https://img-blog.csdnimg.cn/direct/66f9267ce02a4d56923a3a3108c2c0e3.png)

    我们来看 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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
  • 相关阅读:
    Pandas进阶修炼120题-第五期(一些补充,101-120题)
    Json序列化与反序列化导致多线程运行速度和单线程运行速度一致问题
    JAVA集合03_HashSet、LinkedHashSet概述、TreeSet自然顺序、比较器顺序
    LinkedList与链表
    JS正则表达式
    网络黑客入门级工具:netwox
    [python][flask] Flask 入门(以一个博客后台为例)
    CTFSHOW SSTI
    二阶RC滤波器
    suricata 流管理
  • 原文地址:https://blog.csdn.net/u013915286/article/details/138137463