常量是指在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:
const identifier [type] = value
可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
const b string = "abc"
const b = "abc"
多个相同类型的声明可以简写为:
const name1, name2 = value1, value2
package main
import "fmt"
func main() {
const LENGTH int = 10
const WIDTH int = 5
var area int
const a, b, c = 1, false, "str" //多重赋值
area = LENGTH * WIDTH
fmt.Printf("面积为 : %d", area)
println()
println(a, b, c)
}
输出结果为:
面积为 : 50
1 false str
const (
Unknown = 0
Female = 1
Male = 2
)
数字 0、1 和 2 分别代表未知性别、女性和男性。
常量可以用 len()
, cap()
, unsafe.Sizeof()
函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:
在包一级声明语句声明的名字可在整个包对应的每个源文件中访问,而不是仅仅在其声明语句所在的源文件中访问。如下代码中的 a 、 b 、 c 。
package main
import "unsafe"
const (
a = "abc"
b = len(a)
c = unsafe.Sizeof(a)
)
func main(){
println(a, b, c)
}
运行结果为:
abc 3 16
注意:字符串类型在 go
里是个结构, 包含指向底层数组的指针和长度,这两部分每部分都是 8 个字节,所以字符串类型大小为 16 个字节。
iota
特殊常量,可以认为是一个可以被编译器修改的常量。
iota
在 const
关键字出现时将被重置为 0 (const
内部的第一行之前),const
中每新增一行常量声明将使iota
计数一次 ( iota
可理解为 const
语句块中的行索引)。
iota
可以被用作枚举值:
const (
a = iota
b = iota
c = iota
)
第一个 iota
等于 0,每当 iota
在新的一行被使用时,它的值都会自动加 1 ;所以 a=0, b=1, c=2 可以简写为如下形式:
const (
a = iota
b
c
)
使用示例
package main
import "fmt"
func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
}
输出结果为:
0 1 2 ha ha 100 100 7 8
iota
的含义是初始化一个计数器,这个计数器的影响范围只能是 const
后括号作用域范围内的常量。
package main
import (
"fmt"
)
func main() {
const (
a = iota
b
c
d
e
)
const (
A = iota
B
C
D
)
fmt.Println(a, b, c, d, e)
fmt.Println(A, B, C)
}
输出结果如下:
0 1 2 3 4
0 1 2
iota
把初始值 0 赋给 a 后,自增 1,此时 iota
等于1,随后将 1 赋值给常量 b,赋值完成后,iota
又自增 1,此时 iota 等于2,这个自增过程,只会出现在 const
后括号范围内,超过这个括号作为域。再次使用 iota
时,其初始值为 0。从输出结果可知,常量 A 从 0 开始,可以证实这个观点。
package main
import (
"fmt"
)
func main() {
const (
NUM1 = iota
NUM2
NUM3 = iota
NUM4
NUM5
)
const (
A = iota
B
C
D
)
fmt.Println(NUM1, NUM2, NUM3, NUM4, NUM5)
fmt.Println(A, B, C)
}
输出信息是:
0 1 2 3 4
0 1 2
// 错误示例代码
func main() {
const (
a
b
c = iota
d
e
)
fmt.Println(a, b, c, d, e)
}
编译时产生的错误信息:
./hello.go:9:9: missing value in const declaration
./hello.go:10:9: missing value in const declaration
./hello.go:15:17: undefined: a
./hello.go:15:20: undefined: b
从上边的示例代码中可以得知,iota
并不会给括号作用域范围内使用 iota
赋值的那个常量之前的常量赋值,只会给括号作用域内使用 iota
初始化的那个常量后边的所有常量自增 1 后赋值。
iota
默认初始值为 0,我们可以定义的常量初始值从 10 开始,代码如下:
func main() {
const (
a = 10 + iota
b
c
d
e
)
fmt.Println(a, b, c, d, e)
}
输出结果:
10 11 12 13 14
当使用带 iota
的表达式初始化常量时,括号作用域内,后边的常量在初始化时,也会使用这个表达式进行初始化。相当于初始化表达式是:10+1,b 初始化的值是:10+2,以此类推。整个初始化过程中,依然是 iota
在自增 1。
func main() {
const (
a = iota + 10
b = iota
c = iota + 5
d
e
)
fmt.Println(a, b, c, d, e)
}
输出信息是:
10 1 7 8 9
从上边的输出信息可以得知,在使用表达式初始化常量时,会使用离被初始化常量前边最近的那个表达式。如初始化 c 时,使用的是 2+5,初始化 b 时,使用的是 iota
,此时的 iota
值为 1。
在定义常量组时,如果不提供初始值,则表示将使用上行的表达式值。
package main
import "fmt"
const (
a = 1
b
c
d
)
func main() {
fmt.Println(a)
// b、c、d没有初始化,使用上一行(即a)的值
fmt.Println(b) // 输出1
fmt.Println(c) // 输出1
fmt.Println(d) // 输出1
}