导言
- 原文链接: Part 5: Constants
- If translation is not allowed, please leave me in the comment area and I will delete it as soon as possible.
常量
定义
在 Go
中,我们把一些固定的值叫做常量,例如 5
、-89
、"I love Go"
、67.89
…
看看下面的代码先:
var a int = 50
var b string = "I love Go"
在上面的代码中,我们把常量 50
、"I love Go"
分别分配给 a
、b
。
我们可以使用 关键字const
定义常量。虽然在上面的代码中,我并没有显式地使用 const
,但实际在 Go
中,50
、 "I love Go"
就是常量。
再来看个程序:
package main
func main() {
const a = 55 //allowed
a = 89 //reassignment not allowed
}
我们无法给常量重新赋值,因此上面的程序会出现编译错误:
cannot assign to a.
函数与常量
在编译时,常量的数值必须是确定的。因此函数的返回值不能分配给常量,因为函数调用发生在运行时期。
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
是一个常量,它的值必须在编译时期确定。因为在运行时,math.Sqrt(4)
的值才被算出,所以执行 const b = math.Sqrt(4)
时,会抛出一个错误:
main.go:11: const initializer math.Sqrt(4) is not a constant.
字符串常量
在 Go
中,被双引号括起的值 就是 字符串常量。举个例子,“Hello World"
、"Sam"
都是字符串常量。
字符串常量的类型是什么?答案是 无类型 (untyped)。
字符串常量没有类型!
const hello = "Hello World"
在上面的代码中,我们将 "Hello World"
分配给字符串常量 hello
。此时 hello
是没有类型的。
Go
是强类型语言。所有的变量都有一个显性的类型。那么,在下面的程序中,如果我们把 无类型的常量"Sam"
分配给 变量name
,这会发生什么?
package main
import (
"fmt"
)
func main() {
var name = "Sam"
fmt.Printf("type %T value %v", name, name)
}
答案就是:常量都有一个与之相关联的默认类型,当有一行代码用到该常量时,该常量才表现出默认类型。
在上面的 var name = "Sam"
语句 中,name
是需要类型的,而这个类型来自 常量"Sam"
的默认类型 — string
。
我们能创建有类型的常量吗?答案是肯定的,代码如下:
const typedhello string = "Hello World"
在上面的代码中,typehello
就是一个类型为 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"
的默认类型是 string
,所以分配后,defaultName
的类型是 string
。
在下一行,我们定义了一个新的类型 myString
,它来自 string
类型。
之后,我们创建了一个 变量customName
,并将 常量"Sam"
也分配给它。因为 常量"Sam"
是无类型的,所以它能分配给任何 string
类型 的变量。因此,这个分配也是允许的,分配后,customName
的类型为 myString
。
现在,我们拥有了 string
类型 的 defaultName
,以及 myString
类型 的 customName
。但是,即使 myString
是以 string
为基础创建的,Go
语言 的类型政策还是不允许将 string
类型 变量,分配给 myString
类型 变量。
因此,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)
}
在上面的程序中,常量a
是没类型的,它的值为 5
。你可能想知道:
a
的默认类型是什么呢?- 将
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
,而它的句式是通用的 (它可以代表 浮点数、整数、甚至是没有虚部的复数),所以它能被分配给任何兼容的类型 — 这一类常量的默认类型,可以认为是根据上下文动态生成的。
var intVar int = a
要求 a
是 int
类型,所以 a
变为了 int
类型 常量。
var complex64Var complex64 = a
要求 a
是 complex64
类型,所以 a
变为了 complex64
类型 常量。
数字表达式
数字常量的任意混合搭配 构成了 数字表达式,数字表达式也可看作数字常量。
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
都是数字常量,所以表达式 5.9/8
能通过编译。这个表达式的结果是 0.7375
,它是一个浮点数常量,因此 变量a
也为浮点数。
运行上面的程序,输出如下:
a's type float64 value 0.7375.
这就是常量了~
祝你吃好睡好身体棒~
原作者留言
优质内容来之不易,您可以通过该 链接 为我捐赠。
最后
感谢原作者的优质内容。
欢迎指出文中的任何错误。