这是 Golang 教程系列的第 5 个教程。

定义

术语常量在 Go 中用于表示固定值,例如 5,-89,“I love Go”,67.89 等。

思考下面的代码

  1. var a int = 50
  2. var b string = "I love Go"

在上面代码中,a 和 b 分别分配给常数 50,和 I love Go。关键字 const 用于表示常量,比如 50,I love Go。即使我们没有在上面的代码中任何地方明确使用关键字const,但是在 Go 里它们却是常量。

名称表示的常量不能再次分配给任何其他值,因此下面的程序将无法工作,他会编译错误因为无法分配给 a。

  1. package main
  2. func main() {
  3. const a = 55 //allowed
  4. a = 89 //reassignment not allowed
  5. }

Run in playground

在编译时应该知道常量的值。因此他不能分配给函数调用返回的值,因为函数调用是在运行时进行的。

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. func main() {
  7. fmt.Println("Hello, playground")
  8. var a = math.Sqrt(4)//allowed
  9. const b = math.Sqrt(4)//not allowed
  10. }

Run in playground

在上面的程序中,a 是一个变量因此它可以分配给函数 math.Sqrt(4) 的结果。
b 是常量,在编译时需要知道 b 的值。函数 math.Sqrt(4) 将仅在运行时进行计算,因此 const b = math.Sqrt(4) 会抛出错误 error main.go:11: const initializer math.Sqrt(4) is not a constant.

字符串常量

双引号之间的任何职都是Go中的字符串常量。例如像”Hello World”Sam”这样的字符串都是Go的常量。

字符串属于什么类型?答案是它们是无类型的。

像”Hello World”这样的字符串常量没有任何类型。

  1. const hello = "Hello World"

在上面的例子中,我们给命名常量 hello 分配了 “Hello World”。现在 hello 常量有类型吗?答案是否定的,常量仍然没有类型。

Go 是一种强类型语言。所有变量都需要显式类型。那么下面的程序如何给无类型常量 Sam 分配变量名称呢?

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. var name = "Sam"
  7. fmt.Printf("type %T value %v", name, name)
  8. }

Run in playground

答案是无类型常量具有与它们相关联的默认类型,并且当且仅当这行代码需要它时才提供。在语句 var name = "Sam", name 需要一个类型,字符串常量 “Sam” 的默认类型获取这个字符串。

有没有办法创建一个类型常量?答案是肯定的,下面代码将创建一个类型化常量。

  1. const typedhello string = "Hello World"

上面代码中的 typedhello 是类型字符串的常量。
**
Go 是一种强类型语言。不允许在分配期间混合类型。让我们通过一个程序来了解这句话的意思。

  1. package main
  2. func main() {
  3. var defaultName = "Sam" //allowed
  4. type myString string
  5. var customName myString = "Sam" //allowed
  6. customName = defaultName //not allowed
  7. }

Run in playground

在上面代码中,我们首先创建了一个常量 defaultName 并将其分配给常量 Sam 。常量 Sam 的默认类型是字符串,因此在赋值后,defaultName 的类型是字符串类型。
在下一行中,我们创建了一个新类型 myString,它是 string 的别名。

然后我们创建一个 myString 类型的变量 customName 并将其分配给常量 Sam。由于常量 Sam 是无类型的,因此可以将其分配给任何字符串变量。因此,代码中这次赋值是被允许的,所以 customName 获取 myString 类型。

现在我们有一个类型为字符串的变量 defaultName 和另一个类型为 myString 的变量customName。Go 的强类型规定了禁止将一种类型的变量分配给另外一种类型。因此这个赋值 customName = defaultName 是不被允许的,并且编译器还会抛出错误**main.go:7:20: cannot use defaultName (type string) as type myString in assignment

**

布尔常量

布尔常量与字符串常量没有区别。它们是两个无类型常量 true false 。字符串常量的相同规则适用于布尔值,因此我们在此不再重复。下面是解释布尔常量的简单程序。

  1. package main
  2. func main() {
  3. const trueConst = true
  4. type myBool bool
  5. var defaultBool = trueConst //allowed
  6. var customBool myBool = trueConst //allowed
  7. defaultBool = customBool //not allowed
  8. }

Run in playground

数字常量

数字常量包括整数,浮点数和复数常量。数字常量中有一些细微之处。

让我们看一些例子来了解它们。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. const a = 5
  7. var intVar int = a
  8. var int32Var int32 = a
  9. var float64Var float64 = a
  10. var complex64Var complex64 = a
  11. fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
  12. }

Run in playground

在上面程序中,常量 a 是无类型的,其值为 5。你可能想知道 a 的默认类型是什么,如果它有一个默认类型,那么我们如何将它分配给不同类型的变量。答案在于 a 的语法。下面程序将会让你更加清楚。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. var i = 5
  7. var f = 5.6
  8. var c = 5 + 6i
  9. fmt.Printf("i's type %T, f's type %T, c's type %T", i, f, c)
  10. }

Run in playground

在上面的程序中,每个变量的类型由数值常量的语法决定。5 按语法是整数,5.6 是浮点数,5 + 6i 按语法是复数。当上述程序运行时,它会输出 i's type int, f's type float64, c's type complex128

现在,我希望大家能清楚地了解下面的程序是如何工作的。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. const a = 5
  7. var intVar int = a
  8. var int32Var int32 = a
  9. var float64Var float64 = a
  10. var complex64Var complex64 = a
  11. fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
  12. }

Run in playground

在这个程序中,a 的值是 5,a 的语法是通用的(它可以表示浮点数、整数,甚至没有虚部的复数),因此可以分配给任何兼容的类型。这类常量的默认类型可以看作是根据上下文动态生成的。var intVar int = a 要求 a 是整型的,所以它变成了一个整型常量。ar complex64Var complex64 = a 要求 a 是一个复数,因此它变成了一个复数常数。非常整洁有木有。

数字表达式

数值常量可以在表达式中自由混合和匹配,只有在将它们分配给变量,或者用于需要类型的地方的时候才需要类型。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. var a = 5.9/8
  7. fmt.Printf("a's type %T value %v",a, a)
  8. }

Run in playground

在上面的程序中,5.9 是浮点类型,8 是整数类型。5.9 / 8 是被允许的,因为两者都是数字常量。除法的结果是 0.7375 是浮点数,因此变量 a 是 float 类型。程序的输出``a's type float64 value 0.7375

原文链接

https://golangbot.com/constants/