Go语言底层原理剖析
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.1 常量声明与生存周期

在Go语言中使用const关键字来声明常量,在声明时可以指定或省略类型,如下所示。

其中,等式左边的常量叫作命名常量,等式右边的常量叫作未命名常量,拥有未定义的类型。当有足够的内存来存储整数值时,可以始终精确地表示整数。由于Go语言规范中要求整数常量至少能够存储256位,因此在实际中Go语言能涵盖几乎所有的整数常量。

为了获得精确的浮点数,编译器可以采用不同的策略和选项。Go语言规范未说明编译器必须如何执行此操作,但给出了一些强制性的要求[2]

◎ 如果浮点数以(1+mantissa)×(2exponent)表示,那么mantissa至少能表示256位的小数,而exponent至少能够用16 bits表示。

◎ 如果由于溢出而无法表示浮点数或复数常量,则报错。

◎ 如果由于精度限制而无法表示浮点数,则四舍五入表示为最接近的可表示常量。

以下是不同编译器实现精确浮点数的两种策略:

◎ 将所有浮点数表示为分数,并对这些分数进行有理运算。这些浮点数永远不会损失任何精度。

◎ 使用高精度浮点数。当使用具有数百位精度的浮点数时,精确值和近似值之间的差异几乎可以忽略。

可以看到,在Go语言编译器中使用了大数包math/big来处理编译时的大整数和更高精度的浮点数。

未命名常量只会在编译期间存在,因此其不会存储在内存中,而命名常量存在于内存静态只读区,不能被修改。同时,Go语言禁止了对常量取地址的操作,因此下面尝试对常量寻址的代码是错误的。报错为cannot take the address of k。