在 Go 语言中,有两种常量:非显式类型的(untyped)和显式类型的(typed)。这与语言的历史愿望有关,即使类型系统变得灵活和安全,允许编译器在编译阶段发现错误,并仅在允许的地方进行类型转换。
问题 出现于程序员未能区分这两种常量,依赖常量的行为而忽略函数和接口中的类型要求。这可能导致类型转换错误、意外的编译错误或在调用函数时意外的"跳跃"兼容性。
解决方案 在于清楚理解:
const x int = 42),对该常量的后续操作将受所给类型的限制。示例代码:
const Pi = 3.14 // 未显式类型的 const Answer int64 = 42 // 显式类型的 func printInt(a int) { fmt.Println(a) } func main() { printInt(Pi) // 错误:Pi 不是 int(但是可以显式转换) printInt(int(Pi)) // 好 printInt(Answer) // 好,因为 Answer 已经是 int64,而 int64 到 int 是显式转换 }
关键特性:
能否将未显式类型的常量直接赋值为浮点数到 int 类型的变量而不进行转换?
不能。尽管未显式类型的常量可以被插入到不同类型的表达式中,但尝试将浮点常量赋值给 int 类型的变量将导致编译错误。需要显式转换:
const Pi = 3.14 var x int = Pi // 编译器将报错 var y int = int(Pi) // 好
未显式类型常量在第一次赋值操作时会转换为其类型吗?
不会,常量在没有插入到预期特定类型的上下文中或未显式声明之前,仍然保持 untyped。
可以使用大的未显式类型数值常量初始化较小尺寸的变量,如果值可以放入吗?
可以,只要值的绝对值在目标类型的范围内。否则,编译器将报错。
示例:
const Big = 1 << 62 var x int32 = Big // 错误:Big 无法放入 int32 中 var y int64 = Big // 好
在一个复杂的金融项目中,开发人员将一系列常量(百分比、系数)声称为未显式类型常量。有一次,部分函数需要 float32 而不是 float64。自动类型提升导致计算精度的丢失,这一点并没有立即被注意到。
优点:
缺点:
在系统的另一部分,所有常量都通过显式类型声明,转换是在明确的情况下进行:
const Discount float64 = 0.05
优点:
缺点: