go语言 strconv.ParseInt 的实现分析

字符串与数值之间进行转换是一个高频操作,在go语言中,SDK提供 strconv.ParseInt 将字符串转换为数值,strconv.FormatInt 可以将数值转换为字符串。

1.首先看下 strconv.ParseInt 函数如何使用:

func ParseInt(s string, base int, bitSize int) (i int64, err error){}

参数:

  • s:数字的字符串形式
  • base:数字字符串的进制,比如:2进制、10进制。
  • bitSize:预期数值的bit大小,用于数值上限限制,最终返回的还是int64类型

2.下面看下函数的具体实现:

strconv.ParseIntstrconv.ParseUint 的一个包装层,区别在数值结果的基础上处理符号,因此具体的实现在strconv.ParseUint里面。

func ParseUint(s string, base int, bitSize int) (uint64, error) {
        ...
        case base == 0:
                // Look for octal, hex prefix.
                base = 10    // 当base = 0,默认 base 按赋值10进制
                if s[0] == '0' {
                        switch {
                        case len(s) >= 3 && lower(s[1]) == 'b':    // 根据字符串的前缀,来判断二进制。下面同理
                                base = 2
                                s = s[2:]
                        case len(s) >= 3 && lower(s[1]) == 'o':
                                base = 8
                                s = s[2:]
                        case len(s) >= 3 && lower(s[1]) == 'x':
                                base = 16
                                s = s[2:]
                        default:
                                base = 8    // 当 0 开头,默认8进制
                                s = s[1:]
                        }
                }
        default:
                return 0, baseError(fnParseUint, s0, base)
        }
}

根据进制 base 进制数计算数值,支持2~ 36进制[0-9A-Z]

func ParseUint(s string, base int, bitSize int) (uint64, error) {
      ...
      // 逐个字符判断,然后累加求和
      for _, c := range []byte(s) {
                var d byte
                switch {
                case c == '_' && base0:
                        underscores = true
                        continue
                case '0' <= c && c <= '9':
                        d = c - '0'
                 // 支持2 ~ 36进制
                case 'a' <= lower(c) && lower(c) <= 'z':
                        d = lower(c) - 'a' + 10
                default:
                        return 0, syntaxError(fnParseUint, s0)
                }

                if d >= byte(base) {
                        return 0, syntaxError(fnParseUint, s0)
                }

                if n >= cutoff {
                        // n*base overflows
                        return maxVal, rangeError(fnParseUint, s0)
                }
                n *= uint64(base)

                n1 := n + uint64(d)
                if n1 < n || n1 > maxVal {
                        // n+v overflows
                        return maxVal, rangeError(fnParseUint, s0)
                }
                n = n1
        }
}

3.使用strconv.FormatInt将数值转换为字符串

func FormatInt(i int64, base int) string {}

参数:

  • i:10进制数值
  • base:进制数

示例:

 // 将10进制数 15 转换为 16 进制的字符串形式
func Test_FormatUint(t *testing.T) {
        val := strconv.FormatUint(15, 16)
        fmt.Println(val) // output:f
}