2.3 数值类型
Go语言提供了大量内置的数值类型,标准库也提供了big.Int类型的整数和big.Rat类型的有理数,这些都是大小不限的(只限于机器的内存)。每一个数值类型都不同,这意味着我们不能在不同的类型(例如,类型int32和类型int)之间进行二进制数值运算或者比较操作(如+或者<)。无类型的数值常量可以兼容表达式中任何(内置的)类型的数值,因此我们可以直接将一个无类型的数值常量与另一个数值做加法,或者将一个无类型的常量与另一个数值进行比较,无论另一个数值是什么类型(但必须为内置类型)。
如果我们需要在不同的数值类型之间进行数值运算或者比较操作,就必须进行类型转换,通常是将类型转换成最大的类型以防止精度丢失。类型转换采用 type(value)的形式,只要合法,就总能转换成功——即使会导致数据丢失。请看下面的例子。
const factor = 3 // factor与任何数值类型兼容
i := 20000 // 通过推断得出i的类型为int
i *= factor
j := int16(20) // j的类型为int16,与这样定义效果一样:var j int16 = 20
i += int(j) // 类型必须匹配,因此需要转换
k := uint8(0) // 效果与这样定义一样:var k uint8
k = uint8(i) // 转换成功,但是k的值被截为8位
fmt.Println(i, j, k) // 打印:60020 20 16
为了执行缩小尺寸的类型转换,我们可以创建合适的函数。例如:
func Uint8FromInt(x int) (uint8, error) {
if 0 <= x && x <= math.MaxUint8 {
return uint8(x), nil
}
return 0, fmt.Errorf("%d is out of the uint8 range", x)
}
该函数接受一个int型参数,如果给定的int值在给定的范围内,则返回一个uint8和nil,否则返回0和相应的错误值。math.MaxUint8常量来自于math包,该包中也有一些类似的Go语言中其他内置类型的常量。(当然,无符号的类型没有最小值常量,因为它们的最小值都为 0。)fmt.Errorf()函数返回一个基于给定的格式化字符串和值创建的错误值。(字符串格式化的内容将在3.5节讨论。)
相同类型的数值可以使用比较操作符进行比较(参见表 2-3)。类似地,Go语言的算术操作符可以用于数值。表 2-4 给出的算术运算操作符可用于任何内置的数值,而表 2-6 给出的算术运算操作符适用于任何整型值。