2.3.数值类型
Go语言提供了大量的内置数值类型,且标准库也提供了无限大小的big.Int类型的整数和big.Rat类型的有理数(仅受机器内存限制)。每个数值类型都是不同的:这意哧我们不能使用二元算术运算或比较操作(如+或者<)来对不同类型(如类型int32和类型int)的数值进行操作。无类型的数值常量可以兼容表达式中任何(内置)类型的数值,所以我们可以将一个无类型的数值常量与另一个数值进行加法或者比较操作,而不必关心另一个数值的(内置)类型。
如果我们需要在不同类型的数值上执行算术或比较操作,我们必须进行类型转换——通常是转换成最大的类型以避免精度丢失。转换采用type(value)的形式,只要合法就总能转换成功——即使会导致数据丢失。如下例所示:
1 2 3 4 5 6 7 8 | const factor = 3 // factor is compatible with any numeric type i := 20000 // i is of type int by inference i *= factor j := int16(20) // j is of type int16; same as: var j int16 = 20 i += int(j) // Types must match so conversion is required k := uint8(0) // Same as: var k uint8 k = uint8(i) // Succeeds, but k's value is truncated to 8 bits ✗ fmt.Println(i, j, k) // Prints: 60020 20 116 |
我们可以创建合适的函数来执行安全的类型转换。例如:
1 2 3 4 5 6 | 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和error。math.MaxUint8常量来自于math包,该包中也有一些类似的其他内置数值类型的常量。(当然,无符号类型常量没有最小值,因为它们的最小值都为0。)fmt.Errorf()函数返回一个基于格式化字符串和值创建的错误值。
可以使用比较操作符比较相同类型的数值。类似地,Go语言的算术操作符也适用于数值。
表2.4适用于任何内置的数值,而表2.6仅适用于整型值。
+x | x |
-x | x的负值 |
x++ | 为x加上一个无类型的常量1 |
x– | 为x减去一个无类型的常量1 |
x+=y | 将x加上y |
x-=y | 将x减去y |
x*=y | 将x乘以y |
x/=y | 将x除以y,如果这些数字都是整数那么任何余数都被丢弃,除以0会导致运行时异常 |
x+y | x与y的和 |
x-y | x减去y的结果 |
x*y | x乘以y的结果 |
x/y | x除以y的结果,如果这些数字都是整数那么任何余数都被丢弃,除以0会导致运行时异常 |
常量表达式的值在编译时计算;它们可以使用任何算术、布尔以及比较操作符。例如:
1 2 3 4 5 6 | const ( efri int64 = 10000000000 // type: int64 hlutföllum = 16.0 / 9.0 // type: float64 mælikvarða = complex(-2, 3.5) * hlutföllum // type: complex128 erGjaldgengur = 0.0 <= hlutföllum && hlutföllum < 2.0 // type: bool ) |
该示例使用了冰岛语标识符,请记住Go完全支持本土语言标识符。(我们稍后会讨论 complex())。
虽然Go语言拥有比较合理的优先级规则(不同于C或C++),但我们还是推荐使用括号来明确表达式的含义。强烈推荐那些使用多种语言的程序员使用括号以避免一些不易发现的错误。