Go 中的术语常量用于表示固定值,例如:
1 | 95 |
等等。
声明一个常数
1 | package main |
在上面的代码a
中是一个常量,它被赋值50
。
声明一组常量
还有另一种语法可以使用单个语句定义一组常量。下面提供了使用此语法定义一组常量的示例。
1 | package main |
在上面的程序中,我们声明了 3 个常量name
,age
和country
。上面的程序打印,
1 | John |
顾名思义,常量不能再次重新分配给任何其他值。在下面的程序中,我们试图为a
重新赋值89
。 这是不允许的,因为a
它是一个常数。该程序将无法运行,编译错误cannot assign to a.
1 | package main |
常量的值应该在编译时知道。因此,它不能分配给函数调用返回的值,因为函数调用发生在运行时。
1 | package main |
在上面的程序中,a
是一个变量,因此可以将其分配给函数的结果
b是一个常数,需要在编译时知道 b 的值。该函数math.Sqrt(4)
将仅在运行时进行评估,因此const b = math.Sqrt(4)
无法编译并出现错误
1 | ./prog.go:9:8: const initializer math.Sqrt(4) is not a constant |
字符串常量、类型化和非类型化常量
双引号之间的任何值都是 Go 中的字符串常量。例如,像"Hello World"
,这样的字符串在 Go 中都是常量。
字符串常量属于什么类型?答案是它们是无类型的。
像“Hello World”这样的字符串常量没有任何类型。
1 | const hello = "Hello World" |
在上面的代码行中,常量hello
没有类型。
Go 是一种强类型语言。所有变量都需要显式类型。
以下将变量分配给name
的无类型常量n
的程序如何工作?
1 | package main |
答案是无类型常量有一个与之关联的默认类型,当且仅当一行代码需要它时,它们才会提供它。在第 8 行的声明var name = n
中name
需要一个类型,它从字符串常量的默认类型中获取它,n
是一个字符串。
有没有办法创建一个类型化的常量?答案是肯定的。以下代码创建一个类型化常量。
1 | const typedhello string = "Hello World" |
*上面代码中的typedhello
是一个字符串类型的常量。
Go 是一种强类型语言。不允许在分配期间混合类型。让我们在程序的帮助下看看这意味着什么。
1 | package main |
在上面的代码中,我们首先创建一个变量defaultName
并将其分配给常量Sam
。常量Sam
的默认类型是 string
,所以赋值后defaultName
的类型是string
。
在下一行中,我们创建了一个新类型myString
,它是字符串的别名。
然后我们创建一个customName
类型的变量myString
,并将常量Sam
分配给它。由于常量Sam
是无类型的,它可以分配给任何string
变量。因此,允许此分配并获取customName
的 type myString
。
现在我们有一个string
类型的变量defaultName
和另一个customName
类型的变量myString
。尽管我们知道 myString 是 string 的别名,但 Go 的强类型策略不允许将一种类型的变量分配给另一种类型。因此不允许赋值,编译器抛出错误customName = defaultName``./prog.go:7:20: cannot use defaultName (type string) as type myString in assignment
布尔常量
布尔常量与字符串常量没有什么不同。它们是两个无类型常量true
和false
. 字符串常量的相同规则适用于布尔值,因此我们不会在这里重复它们。下面是一个解释布尔常量的简单程序。
1 | package main |
上面的程序是不言自明的。
数值常数
数值常量包括整数、浮点数和复数常量。数值常量有一些微妙之处。
让我们看一些例子说明清楚。
1 | package main |
在上面的程序中, consta
是untyped
type并且有一个 value 5
。您可能想知道 a 的默认类型是什么,如果它确实有,我们如何将它分配给不同类型的变量。答案在于a
的语法. 下面的程序会让事情变得更清楚。
1 | package main |
在上面的程序中,每个变量的类型由数值常量的语法决定。5在语法上是整数,5.6是浮点数,5 + 6i在语法上是复数。当上面的程序运行时,它会打印:
1 | i's type is int, f's type is float64, c's type is complex128 |
有了这些知识,让我们试着理解下面的程序是如何工作的。
1 | package main |
在上面的程序中, a
的值是5
并且语法a
是通用的。它可以表示浮点数、整数甚至是没有虚部的复数。因此可以分配给任何兼容的类型。这些常量的默认类型可以被认为是根据上下文动态生成的。var intVar int = a
需要a
是 int
type所以它变成一个int
常数。var complex64Var complex64 = a
需要a
是一个复数,因此它成为一个复数常数。挺整洁的 :)。
数值表达式
数值常量可以在表达式中自由混合和匹配,并且只有在将它们分配给变量或在需要类型的代码中的任何地方使用时才需要类型。
1 | package main |
在上面的程序中,5.9
按语法是浮点数,按语法8
是整数。尽管如此,5.9/8
还是允许的,因为两者都是数字常量。除法的结果是 0.7375 是float
类型,因此变量 a的类型是float
。程序的输出是:
1 | a's type is float64 and value is 0.7375 |