字符串转整型 strconv.ParseInt 第三个参数的作用是什么?

xuanwen · · 3305 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

#### 问题来源 刚才查资料的时候,看到帖子 https://studygolang.com/articles/2231 根据帖子的表述,我理解为 ```golang i, err := strconv.ParseInt("123", 10, 32) 的意思是 (字符串123 , 十进制,int32) i 返回的结果为 123 的类型 是 int32 如果代码改成下面这样的 i, err := strconv.ParseInt("123", 10, 64) 的意思是 (字符串123 , 十进制,int64) i 返回的结果为 123 的类型 是 int64 ``` <br/> 我写了一个例子感觉结果不符合预期 ```golang package main import ( "fmt" "github.com/imroc/biu" "reflect" "strconv" ) func main() { a := "1" aNumber, err := strconv.ParseInt(a, 10, 64) // string 转 int64 if err != nil { panic(err) } b := "1" bNumber, err := strconv.ParseInt(b, 10, 32) // string 转 int32 if err != nil { panic(err) } c := "1" cNumber, err := strconv.ParseInt(c, 10, 8) // string 转 int8 if err != nil { panic(err) } fmt.Printf("a %s %s 转整型 结果为: %s %d \n", reflect.TypeOf(a), a, reflect.TypeOf(aNumber), aNumber) fmt.Printf("b %s %s 转整型 结果为: %s %d \n", reflect.TypeOf(b), b, reflect.TypeOf(bNumber), bNumber) fmt.Printf("c %s %s 转整型 结果为: %s %d \n", reflect.TypeOf(c), c, reflect.TypeOf(cNumber), cNumber) fmt.Println("a 内存地址 ", &a) fmt.Println("b 内存地址 ", &b) fmt.Println("c 内存地址 ", &c) fmt.Println("a bit细节 ", biu.ToBinaryString(aNumber)) fmt.Println("b bit细节 ", biu.ToBinaryString(bNumber)) fmt.Println("c bit细节 ", biu.ToBinaryString(cNumber)) } ``` <br/> **运行结果** ```golang a string 1 转整型 结果为: int64 1 b string 1 转整型 结果为: int64 1 c string 1 转整型 结果为: int64 1 a 内存地址 0xc000010280 b 内存地址 0xc000010290 c 内存地址 0xc0000102a0 a bit细节 [00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001] b bit细节 [00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001] c bit细节 [00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001] ``` <br/> **结果好像不符合预期?不管是64,32,还是8,返回的结果都是int64<br/> 我有点困惑,不知道是我理解错误?还是我测试的代码有问题?<br/> 为此我找到函数源码,函数源码如下 ** <br/> ```golang // ParseInt interprets a string s in the given base (0, 2 to 36) and // bit size (0 to 64) and returns the corresponding value i. // // If base == 0, the base is implied by the string's prefix: // base 2 for "0b", base 8 for "0" or "0o", base 16 for "0x", // and base 10 otherwise. Also, for base == 0 only, underscore // characters are permitted per the Go integer literal syntax. // If base is below 0, is 1, or is above 36, an error is returned. // // The bitSize argument specifies the integer type // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 // correspond to int, int8, int16, int32, and int64. // If bitSize is below 0 or above 64, an error is returned. // // The errors that ParseInt returns have concrete type *NumError // and include err.Num = s. If s is empty or contains invalid // digits, err.Err = ErrSyntax and the returned value is 0; // if the value corresponding to s cannot be represented by a // signed integer of the given size, err.Err = ErrRange and the // returned value is the maximum magnitude integer of the // appropriate bitSize and sign. func ParseInt(s string, base int, bitSize int) (i int64, err error) { const fnParseInt = "ParseInt" if s == "" { return 0, syntaxError(fnParseInt, s) } // Pick off leading sign. s0 := s neg := false if s[0] == '+' { s = s[1:] } else if s[0] == '-' { neg = true s = s[1:] } // Convert unsigned and check range. var un uint64 un, err = ParseUint(s, base, bitSize) if err != nil && err.(*NumError).Err != ErrRange { err.(*NumError).Func = fnParseInt err.(*NumError).Num = s0 return 0, err } if bitSize == 0 { bitSize = int(IntSize) } cutoff := uint64(1 << uint(bitSize-1)) if !neg && un >= cutoff { return int64(cutoff - 1), rangeError(fnParseInt, s0) } if neg && un > cutoff { return -int64(cutoff), rangeError(fnParseInt, s0) } n := int64(un) if neg { n = -n } return n, nil } ``` <br/> 原谅我不太好的英文,我用谷歌翻译了一下这个函数的注释,下面是翻译结果 <br/> >ParseInt解析给定基数(0、2到36)和位大小(0到64)中的字符串s,并返回相应的值i。 >如果base == 0,则该字符串的前缀隐含基数:“ 0b”的基数为2,“ 0”或“ 0o”的基数为8,“ 0x”的基数为16,否则为10。此外,仅对于base == 0,根据Go整数文字语法允许使用下划线字符。如果base小于0,小于1或大于36,则返回错误。 >bitSize参数指定结果必须适合的整数类型。位大小0、8、16、32和64分别对应于int,int8,int16,int32和int64。如果bitSize小于0或大于64,则返回错误。 >ParseInt返回的错误的具体类型为* NumError,其中包括err.Num = s。如果s为空或包含无效数字,则err.Err = ErrSyntax,返回值为0;否则,返回0。如果与s对应的值不能用给定大小的有符号整数表示,则err.Err = ErrRange,并且返回的值是适当的bitSize和sign的最大大小整数。 里面对于第三个参数是这样解释的 bitSize参数指定结果必须适合的整数类型。位大小0、8、16、32和64分别对应于int,int8,int16,int32和int64。如果bitSize小于0或大于64,则返回错误。 好像与帖子的 参数3 返回结果的bit大小 也就是int8 int16 int32 int64有异曲同工之妙 但是根据我的例子,**<span style="color:red">我不太明白strconv.ParseInt的第三个参数的作用是什么?</span>**<br/> 不管是64,还是32,还是8,返回的结果都是int64 **我的go环境** ```bash $ go version go version go1.13 linux/amd64 $ go env GO111MODULE="on" GOARCH="amd64" GOBIN="" GOCACHE="/**/.cache/go-build" GOENV="/**/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/**/study/languages/go/golangWork" GOPRIVATE="" GOPROXY="https://goproxy.io,direct" GOROOT="/**/opt/softTarget/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/**/opt/softTarget/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/dev/null" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build285609338=/tmp/go-build -gno-record-gcc-switches" ``` <br/> 最后解释一下为啥没在原帖下面回复,主要是内容有点多,而且原帖2015-01-22发布的,新帖发布之后,我会在原帖回复一个新帖的链接

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3305 次点击  ∙  2 赞  
加入收藏 微博
2 回复  |  直到 2020-09-18 03:04:34
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传