3.4.2 常量的类型提升机制

在Go语言中,变量的类型提升或者说隐式类型转换是不被直接支持的,这样的设计可以避免一些因隐式类型转换而导致的潜在问题。不过,Go语言中的常量有一些特殊的类型提升机制,未显式指定类型的常量被称为“无类型”常量,这样的常量在编译时会被隐式地转换为合适的类型。例如,当无符号整数类型与有符号整数类型进行运算时,会自动将无符号整数类型提升为有符号整数类型,以避免可能出现的错误。另一个例子是当一个变量被赋值为一个常量时,如果常量被视为更高级别的数据类型,则变量的数据类型将自动提升为更高级别的。

需要注意的是,类型提升只会在特定的情况下发生,并不是所有情况下都会自动提升类型。因此,在编写代码时,仍然需要注意数据类型的匹配与转换。

下面这个示例演示了将int类型提升为float类型以及将不带类型的常量提升为带类型的常量的过程。

const int_n = 10
const float_e = 2.71828
 
var v = int_n*float_e

上述示例是基于10与2.71828做乘法运算。从字面上看,这是一个整数和一个浮点数相乘。在Go语言中,不支持让两个不同类型的变量之间发生隐式类型转换。但是常量相对特殊,编译器可以在变量和常量之间进行隐式类型转换。在Go语言中,字面量是不带类型的常量。由于常量int_n和float_e只有值,没有给出明确的类型,因此会根据类型提升机制,把常量10从整数常量提升为浮点数常量。这样一来,乘号两边就是相同类型的常量了。

接下来是一个有趣的内容,将int_n*float_e的值赋给变量v后,会降低结果的精度。这是因为常量的精度是256位,而变量v的精度只有64位,这样一来,结果的精度就从256位下降到了64位。

另外,常量与常量之间的运算也可能导致精度下降。示例代码如下。

const i int8 = 1
const j  = 2*i

常量i限制了类型为int8,所以精度是8位。而常量j没有限制类型,所以精度是256位。但是将i的值赋给j后,根据类型提升机制,j的精度就会从256位下降到8位。

需要注意的是,常量仅存在于编译期。下面这段代码在编译时不会报错。

const i = 123456789012345678901234567890 //编译时不会报错