本文为译文。原文地址:constant
常量的声明
声明一个常量
package main
import (
"fmt"
)
func main() {
const a = 50
fmt.Println(a)
}
声明一组常量
package main
import (
"fmt"
)
func main() {
const (
name = "John"
age = 50
country = "Canada"
)
fmt.Println(name)
fmt.Println(age)
fmt.Println(country)
}
常量,顾名思义不可被二次赋值。同时常量的值在编译期就必须明确,不可在运行期在分配。
package main
func main() {
const a = 55 //allowed
a = 89 //reassignment not allowed
const b = math.Sqrt(4) //not allowed. when assigned a value to b in runtime
}
字符串常量、类型和非类型常量
在go里所有通过双引号包裹的值都是stirng 常量。例如"Hello World", "Sam" 在go中都是常量。
string常量属于什么类型?答案是untyped
一个string常量比如"hello world"是没有任何类型的。
const hello = "Hello World"
//hello常量是没有任何类型的。 我们将其称为非类型常量
GO是强类型语言,所有的变量都必须有一个明确的类型。我们看下面的程序
下面的程序为什么我们分配给变量name一个非类型常量n,也是可以工作的呢?
package main
import (
"fmt"
)
func main() {
const n = "Sam"
var name = n
fmt.Printf("type %T value %v", name, name)
}
答案是:untyped constant 会有一个与之相关的默认类型。只有当代码需要其时,其才会提供该类型。在第9行我们声明**var name = n**,name需要一个类型,然后它获取该类型从字符串常量n的默认类型string。(name needs a type and it gets it from the default type of the string constant n which is a string)
那我们如何能创建一个类型常量?
const typedhello string = "Hello World"
//typedhello in the above code is a constant of type 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的别名。
然后我们创建一个myString类型的变量customName然后为其分配一个值叫"Sam"。因为常量"Sam"是无类型的,所以其可以被分配给任何string类型的变量。
现在我们有一个string类型的变量defaultName和一个myString类型的变量customName。即使我们知道myString类型其实就是string类型的别名。但是还是报错了。Go的强类型策略,不允许将一个类型的变量值分配给另一个。因此赋值操作**customName = defaultName**是不被允许的,编译器在编译阶段就会报错**./prog.go:7:20: cannot use defaultName (type string) as type myString in assignment**
布尔常量
基本原则和字符串常量一致。
package main
func main() {
const trueConst = true
type myBool bool
var defaultBool = trueConst //allowed
var customBool myBool = trueConst //allowed
defaultBool = customBool //not allowed
}
数字常量
数字常量包含integers, floats and complex constants。在数字常量中和其他类型比有一些微妙之处。
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)
}
intVar 5
int32Var 5
float64Var 5
complex64Var (5+0i)
上面的const 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 is %T, f's type is %T, c's type is %T", i, f, c)
}
上面的程序,每一个变量的类型取决于数字常量的语法。5是一个整形、5.6是一个浮点型、5+6i是一个复数。当以上程序运行,打印如下
i's type is int, f's type is float64, c's type is 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的类型是通用的(原文a的语法是通用的,感觉怪怪的 the value of a is 5 and the syntax of a is generic)。它可以代表一个float integer 甚至一个没有虚部的complex。因此其可以被分配给任何一个类型兼容的变量。这种常量的默认值可以被认为是根据上下文生成的。var intVar int = a要求a是一个是一个int型所以其变成了一个int常量 var complex64Var complex64 = a要求a是一个复数,因此a变成了一个复数产量。
数字表达式
在表达式中,数字类型可以任意混合。只有在赋值操作或者使用的时候才需要一个类型上的理解。
package main
import (
"fmt"
)
func main() {
var a = 5.9 / 8
fmt.Printf("a's type is %T and value is %v", a, a)
}
上面的程序5.9是一个float类型8是一个integer。但是表达式 5.9 / 8是合法的语法。其结果为0.7375是一个float类型,所以变量a是一个float类型。程序输出如下
a's type is float64 and value is 0.7375