[ Golang 入门教程 ] 第5节——常量
定义
常量在Go中用于表示固定值,例如5,-89,“I love Go”,67.89等。
以下代码,
var a int = 50
var b string = "I love Go"
在上面的代码中,a和b分配给常数 50 和 I love Go。关键字 const 用于表示常量。即使我们在上面的代码中没有明确地使用关键字const,但在内部它们是Go中的常量。
定义为常量后不能再次重新分配给任何其他值,因此下面的程序将编译错误 cannot assign to a
。
package main
func main() {
const a = 55 //允许
a = 89 //不允许
}
在编译时应知道常量的值。因此,不能分配给常量 调用函数返回的值,因为函数调用是在运行程序时进行的。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println("Hello, playground")
var a = math.Sqrt(4)//allowed
const b = math.Sqrt(4)//not allowed
}
在上面的程序中,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”这样的字符串常量没有任何类型。
const hello = "Hello World"
在上面的例子中,我们为命名常量hello分配了“Hello World” 。现在常量hello有一个类型吗?答案是否定的。常数仍然没有类型。
Go是一种强类型语言。所有变量都需要显式类型。那么以下程序如何为变量name
分配无类型常量Sam
?
package main
import (
"fmt"
)
func main() {
var name = "Sam"
fmt.Printf("type %T value %v", name, name)
}
*答案是无类型常量具有与它们相关联的默认类型,并且当且仅当一行代码需要它时才提供它。在语句中var name = "Sam"
,name
需要一个类型,它从字符串常量“Sam”的默认类型获取它,这是一个字符串。*
有没有办法创建一个类型常量?答案是肯定的。以下代码创建一个类型常量。
const typedhello string = "Hello World"
上面代码中的typedhello是string类型的常量。
Go是一种强类型语言。不允许在分配期间混合类型。让我们通过一个程序来看看这意味着什么。
package main
func main() {
var defaultName = "Sam" //allowed
type myString string
var customName myString = "Sam" //allowed
customName = defaultName //not allowed
}
在上面的代码中,我们首先创建一个变量defaultName并将其分配给常量Sam。常量Sam的默认类型是字符串,因此在赋值后,defaultName的类型为 字符串。
在下一行中,我们创建一个新类型 myString,它是 string 的别名。
然后我们创建一个myString类型的变量 customName 并将其分配给常量Sam。由于常量Sam是无类型的,因此可以将其分配给任何字符串变量。因此,这里允许赋值,并且customName获取myString类型。
现在我们有一个类型为string的变量defaultName和另一个类型为myString的变量customName。即使我们知道myString是字符串的别名,Go的强类型策略也不允许将一种类型的变量分配给另一种类型。因此,不允许赋值customName = defaultName,并且编译器抛出错误 main.go:7:20: cannot use defaultName (type string) as type myString in assignment
布尔常量
布尔常量与字符串常量没有区别。它有两个类型化常量true和false。字符串常量的规则同样适用于布尔值,因此我们在此不再重复。以下是解释布尔常量的简单程序。
package main
func main() {
const trueConst = true
type myBool bool
var defaultBool = trueConst //allowed
var customBool myBool = trueConst //allowed
defaultBool = customBool //not allowed
}
数字常量
数字常量包括整数,浮点数和复数常量。数字常量中有一些细微之处。
让我们看一些例子。
package main
import (
"fmt"
)
func main() {
const a = 5
var intVar int = a
var int32Var int32 = a
var float64Var float64 = a
var complex64Var complex64 = a
fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}
在上面的程序中,const a是无类型的并且值为5. 您可能想知道a的默认类型是什么,如果它有一个,那么我们如何将它分配给不同类型的变量。答案在于a的语法。以下程序将使事情更加清晰。
package main
import (
"fmt"
)
func main() {
var i = 5
var f = 5.6
var c = 5 + 6i
fmt.Printf("i's type %T, f's type %T, c's type %T", i, f, c)
}
在上面的程序中,每个变量的类型由数字常量的语法决定。5是整数,5.6是浮点数,5 + 6i是复数。运行上述程序时,会打印出来i's type int, f's type float64, c's type complex128
现在我想下面的程序如何运作将会很清楚了。
package main
import (
"fmt"
)
func main() {
const a = 5
var intVar int = a
var int32Var int32 = a
var float64Var float64 = a
var complex64Var complex64 = a
fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}
在这个程序中,a的值是5,a的语法是通用的(它可以表示浮点数,整数甚至是没有虚部的复数),因此可以将其分配给任何兼容类型。这些常量的默认类型可以被认为是根据上下文动态生成的。var intVar int = a
要求a为int,因此它变为int常量。var complex64Var complex64 = a
要求a是一个复数,因此它变成一个复数常数。简单明了 :)。
数字表达式
数值常量可以在表达式中自由混合和匹配,只有在将它们分配给变量或在需要类型的代码中使用时才需要类型。
package main
import (
"fmt"
)
func main() {
var a = 5.9/8
fmt.Printf("a's type %T value %v",a, a)
}
在上面的程序中,5.9
是一个浮点语法,并且8
是一个整数的语法。允许仍为 5.9/8
,因为两者都是数字常量。除法的结果是0.7375是浮点数,因此变量a是float类型。该程序的输出是a's type float64 value 0.7375
。