整数 与 字符串
// 字符串与其他类型的转换
// str 转 int
newStr1 := "1"
intValue, _ := strconv.Atoi(newStr1)
fmt.Printf("%T,%d\n", intValue, intValue) // int,1
// int 转 str
intValue2 := 1
strValue := strconv.Itoa(intValue2)
fmt.Printf("%T, %s\n", strValue, strValue)
Golang 进阶:strconv – 字符串和基本数据类型之间转换
func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
func Atoi(s string) (i int, err error)
我们最常用的应该就是 Atoi() 了,而这个函数时 ParseInt 的一个简易版。在 Atoi 函数的内部,我们可以看到:
// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.
func Atoi(s string) (int, error) {
...
// Slow path for invalid or big integers.
i64, err := ParseInt(s, 10, 0)
}
也就是说 Atoi 相当于是 ParseInt(s, 10, 0)。所以我们来着重看一下 ParseInt 函数。
ParseInt 函数中有两个参数,其中参数 base 代表字符串将按照给定的 进制 进行转化。
一般的,base 的取值为 2~36,如果 base 的值为 0,则会根据字符串的前缀来确定 base 的值:0x 表示 16 进制; 0 表示 8 进制;否则就是 10 进制。
而第三个参数 bitSize 则表示的是整数的具体类型。取值 0、8、16、32 和 64 分别代表 int、int8、int16、int32 和 int64。
在 bitSize=0 时,这是一种比较特殊的情况,而对于这种情况,在源码中,是对 0 进行了这样转换:
const intSize = 32 << uint(^uint(0)>>63)
const IntSize = intSize // number of bits in int, uint (32 or 64)
ParseInt 函数是有返回值的,而且返回值有两个,n 和 err,err 我们很好理解,而且返回的两种错误值我们在前面也已经提及,我们要说一下,n 返回的是什么内容,在这里,n 返回的是 bitSize 能够表示的最大或最小值。
另外,ParseInt 返回的是 int64,这是为了能够容纳所有的整型,在实际使用中,可以根据传递的 bitSize,然后将结果转为实际需要的类型。
除了将字符串转化为整型的需求,将整型转换为字符串也是同样需要的。我们同样还是需要借助 strconv 这个包:
func FormatUint(i uint64, base int) string // 无符号整型转字符串
func FormatInt(i int64, base int) string // 有符号整型转字符串
func Itoa(i int) string
其中,Itoa 内部直接调用 FormatInt(i, 10) 实现的。base 参数可以取 2~36(0-9,a-z)。
而具体实现的方法则是将整数每一位数字对应到相应的字符,存入字符数组中,最后字符数组转为字符串即为结果。在具体实现时,当 base 是 2 的幂次方时,有优化处理(移位和掩码);十进制也做了优化。
除此之外,在库中还提供了两个函数:AppendInt 和 AppendUint。这两个函数不是将整数转为字符串,而是将整数转为字符数组 append 到目标字符数组中。
Go中字符串和布尔值之间的转换比较简单,主要有三个函数:
// 接受 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False 等字符串;
// 其他形式的字符串会返回错误
func ParseBool(str string) (value bool, err error)
// 直接返回 "true" 或 "false"
func FormatBool(b bool) string
// 将 "true" 或 "false" append 到 dst 中
// 这里用了一个 append 函数对于字符串的特殊形式:append(dst, "true"...)
func AppendBool(dst []byte, b bool)
这里同样涉及到三个函数:
func ParseFloat(s string, bitSize int) (f float64, err error)
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int)
函数的命名和作用跟上面讲解的其他类型一致。
但由于浮点数有精度的问题,精度不一样,ParseFloat 和 FormatFloat 可能达不到互逆的效果。如:
s := strconv.FormatFloat(1234.5678, 'g', 6, 64)
strconv.ParseFloat(s, 64)
特别地(不区分大小写),+inf/inf,+infinity/infinity,-inf/-infinity 和 nan 通过 ParseFloat 转换分别返回对应的值(在 math 包中定义)。
字符串转浮点数:func ParseFloat(s string, bitSize int) (f float64, err error);
bitSize这个参数没什么用;ParseFloat这个函数无论如何都会返回float64
// str 转 float
string3 := "3.1415926"
f,_ := strconv.ParseFloat(string3, 32)
fmt.Printf("%T, %f\n", f, f) // float64, 3.141593
//float 转 string
floatValue := 3.1416926
//4个参数,1:要转换的浮点数 2. 格式标记(b、e、E、f、g、G)
//3. 精度(保留的位数,会四舍五入) 4. 指定浮点类型(32:float32、64:float64)
// 格式标记:
// ‘b’ (-ddddp±ddd,二进制指数)
// ‘e’ (-d.dddde±dd,十进制指数)
// ‘E’ (-d.ddddE±dd,十进制指数)
// ‘f’ (-ddd.dddd,没有指数)
// ‘g’ (‘e’:大指数,‘f’:其它情况)
// ‘G’ (‘E’:大指数,‘f’:其它情况)
//
// 如果格式标记为 ‘e’,‘E’和’f’,则 第三个参数prec 表示小数点后的数字位数
// 如果格式标记为 ‘g’,‘G’,则 第三个参数prec 表示总的数字位数(整数部分+小数部分)
formatFloat := strconv.FormatFloat(floatValue, 'b', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat) // string,7085496630423380p-51
formatFloat = strconv.FormatFloat(floatValue, 'e', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat) // string,3.15e+00
formatFloat = strconv.FormatFloat(floatValue, 'E', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat) // string,3.15E+00
formatFloat = strconv.FormatFloat(floatValue, 'f', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat) // string,3.15
formatFloat = strconv.FormatFloat(floatValue, 'g', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat)// string,3.1
formatFloat = strconv.FormatFloat(floatValue, 'G', 2, 64)
fmt.Printf("%T,%s \n", formatFloat, formatFloat) // string,3.1