2-3 Go --- 常量
一、什么是常量
常量通常指常规的固定值。如:一天24小时、一年有12个月、平年一年是365天、闰年一年是366天、班级里有50名学生......
二、什么使用常量
因为程序的运行,有时需要一个固定的值作为一个定值,如圆周率作为一个固定不变的值 3.1415926,防止在程序中改变这个值所以设置为常量。
三、如何使用常量
1、常量的定义和变量的定义相似,只是把 var 换成了const 关键字。
2、常量在定义的时候必须赋值,随后不能再被赋值,否则编译出错。
3、常量可以只定义不使用。
1)、只初始化常量不使用。
package main
func main() {
//定义常量关键字 const
const month int = 12 // 初始化一个名为month常量
/*常量可以只初始化不使用,没有执行打印输出也不会报错。
变量只要初始化了就要使用。*/
}
2)、常量定义一定要赋值,不然会报错。
3)、批量初始化常量
(1)、完整式 —— 批量初始化同类型常量。
package main
import "fmt"
func main() {
// 完整式 —— 批量初始化同类型常量。
const n1, n2 int = 100, 200 //初始化n1、n2。值为100,200
fmt.Println(n1,n2)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
100 200
(2)、类型推导式 —— 批量初始化同类型常量 。类型推导定义常量(变量)不用写类型。go 会判断值的的类型来设置常量(变量)的类型。
package main
import "fmt"
func main() {
// 类型推导式 —— 批量初始化同类型常量。
const n3, n4 = 300, 400 //初始化n3、n4。值为300,400
fmt.Println(n3, n4)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
300 400
(3)、类型推导式 —— 批量分段初始化多类型常量 。
package main
import "fmt"
func main() {
// 类型推导式 —— 批量分段初始化多类型常量。
const (
n5, n6 = 500, 600 //初始化n5、n6。值为500,600
s1, n7 = "s1是字符串", 700 //初始化s1、n7。值为"s1是字符串",700
s2 = "s2也是字符串" //初始化s2。值为"s2也是字符串"
)
fmt.Println(n5, n6, s1, n7, s2)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
500 600 s1是字符串 700 s2也是字符串
也可以把分段的初始化内容写成一段:
package main
import "fmt"
func main() {
// 类型推导式 —— 批量初始化多类型常量。
//初始化n5,n6,s1,n7,s2。值为500,600,"s1是字符串",700,"s2也是字符串"
const n5, n6, s1, n7, s2 = 500, 600, "s1是字符串", 700, "s2也是字符串"
fmt.Println(n5, n6, s1, n7, s2)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
500 600 s1是字符串 700 s2也是字符串
(4)、常量不能用简短式初始化。变量名 := 值 这种简短式只适用于初始化变量,常量的定义需要用到 const 关键字。n8 := 800 提示的报错 n8 declared but not used —— n8 已经定义,但没有使用。n8 := 800 这样的表达式被认为变量定义的报错。因为变量定义需要使用才有意义。go 不认为这是初始化常量。
(5)、const 同时定义很多个常量的时候,如果省略赋值则默认和上一行的值一样。
package main
import "fmt"
func main() {
//批量初始化常量时,如果省略了值则跟上一行的值一样。
const (
n8 = 800 // n8的值是800
n9 // n9不赋值,默认跟n8的值800
n10 //n10不赋值,默认跟n9的值800
)
fmt.Println(n8, n9, n10)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
800 800 800

当有新的常量赋值出现时,下一行不赋值的常量就会跟上一行的常量值。好像 n11赋值1100,n12不赋值,它不会跟之前一样输出800,而是跟n11的值1100。n13赋值1300,n14,n15不赋值也不跟n12一样输出1100,而是跟n13一样输出1300。
package main
import "fmt"
func main() {
//批量初始化常量时,如果省略了值则跟上一行的值一样。
const (
n8 = 800 // n8的值是800,输出800
n9 // n9不赋值,默认跟n8的值800
n10 //n10不赋值,默认跟n9的值800
n11 = 1100 //n11赋值1100,输出1100
n12 //n12不赋值,默认跟上一行n11的值1100
n13 = 1300 //n13赋值1300,输出1300
n14 //n14不赋值,默认跟上一行n13的值1300
n15 //n15不赋值,默认跟上一行n14的值1300
)
fmt.Println(n8, n9, n10)
fmt.Println(n11, n12, n13, n14, n15)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
800 800 800
1100 1100 1300 1300 1300

总之,记住批量赋值的时候,不赋值的常量就是跟上一行的值。
另外,用这种方式去初始化常量只适用于这种分段式,不能用在单行的初始化形式,因为单行的初始化形式需要左右的数目一致。左边有多少常量,右边就要对应多少值。不然会报错。

四、iota 常量累计器
1)、iota 只能在常量表达式种使用,变量表达式用 iota 会报错。

2)、const 关键字第一个常量是 iota 时值将被置为数字0。
package main
import "fmt"
func main() {
//const第一个常量是iota时,值为0。
const (
n0 = iota
)
fmt.Println(n0)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
0
3)、const 中每新增一行常量声明将使 iota 值加1。
package main
import "fmt"
func main() {
//const中每增加一行常量声明,iota自增1。
const (
n0 = iota //iota=0,n0=0
n1 /*n1不赋值,默认上一行iota,由于const新增一行常量声明iota自增 1
所以iota=1,n1=1。*/
n2 //同理,新增一行常量声明 iota 就自增1,此时iota=2,n2=2
n3 //iota=3,n3=3
)
fmt.Println(n0, n1, n2, n3)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
0 1 2 3
4)、iota作为累计器
package main
import "fmt"
func main() {
//根据const中每增加一行常量声明,iota自增1的特性。
const (
n1 = iota + 1 //iota=0,+1=1赋值给n1
n2 //通过iota自增1,+1的表达式赋值到常量,完成累加。
n3
n4
n5
n6
n7
n8
n9
n10
)
fmt.Println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
1 2 3 4 5 6 7 8 9 10
5)、iota累减
package main
import "fmt"
func main() {
//根据const中每增加一行常量声明,iota自增1的特性。
const (
n1 = 10 - iota //iota=0,10-0赋值给n1,n1=10
n2 //iota自增1,10-1赋值给n2,n2=9
n3 //iota自增1,10-2赋值给n3,n3=8
n4 //iota自增1,10-3赋值给n4,n4=7
n5 //iota自增1,10-4赋值给n5,n5=6
n6 //iota自增1,10-5赋值给n6,n6=5
n7 //iota自增1,10-6赋值给n7,n7=4
n8 //iota自增1,10-7赋值给n8,n8=3
n9 //iota自增1,10-8赋值给n9,n9=2
n10 //iota自增1,10-9赋值给n10,n10=1
)
fmt.Println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
10 9 8 7 6 5 4 3 2 1
6)、中间插队为常量赋值,iota仍会继续执行。
package main
import "fmt"
func main() {
//给常量赋值,只要新增常量,iota仍会执行自增。
const (
n1 = iota //iota=0赋值给n1,n1=0
n2 //iota自增1赋值给n2,n2=1
n3 //iota自增1赋值给n3,n3=2
n4 = 400 //n4赋值400,n4=400。iota自增1,iota=3
n5 //n5没有赋值,跟上一行n4的值。n5=400,iota自增1,iota=4
n6 //n6没有赋值,跟上一行n5的值。n6=400,iota自增1,iota=5
n7 = 700 //n7赋值700,n7=700。iota自增1,iota=6
n8 //n8没有赋值,跟上一行n7的值。n8=700,iota自增1,iota=7
n9 = iota //iota自增1赋值给n9,n9=8
n10 //n10没有赋值,跟上一行n9的值。n9=8,iota自增1,iota=9
)
fmt.Println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
0 1 2 400 400 400 700 700 8 9
7)、const创建常量的时候就可以用 iota。每次 const 出现时,都会让 iota 初始化为0。
package main
import "fmt"
func main() {
const (
a = iota // const 后跟的是 iota,iota 初始化为0
)
fmt.Println(a)
const (
b = iota // 另一个 const 出现,后面跟的也是 iota。iota 初始化为0
c
)
fmt.Println(b, c)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
0
0 1
8)、const()括号批量创建常量的时候,每创建一个常量,iota就会自增1,也就是累加。所以,随时把常量赋值为iota,iota都能显示出当前的累计数。如下面的例子最后一个常量n10赋值 iota,iota显示出当前累加值。也可以证明批量创建常量的时候,iota已经根据常量的数量进行累加计算。
package main
import "fmt"
func main() {
//给常量赋值,只要新增常量,iota仍会执行自增。
const (
n1 = 100 //n1=100,ioto=0
n2 = 200 //n2=200,ioto=1
n3 = 300 //n3=300,ioto=2
n4 = 400 //n4=400,ioto=3
n5 = 500 //n5=500,ioto=4
n6 = 600 //n6=600,ioto=5
n7 = 700 //n7=700,ioto=6
n8 = 800 //n8=800,ioto=7
n9 = 900 //n9=900,ioto=8
n10 = iota //iota自增1,iota=9
)
fmt.Println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
100 200 300 400 500 600 700 800 900 9
赋值 和 iota的关系:
1、常量指定赋值,显示赋值。iota 也会累加。
2、常量指定iota,显示iota值。
3、常量不赋值,上一层有赋值则跟上一层赋值。上一层是iota则显示本层累加的iota值。
9)、有时不想要的 iota 值,可以用 _ 下划线进行跳过。
package main
import "fmt"
func main() {
//跳过iota。
const (
n0 = iota //ioto=0
n2 //ioto=1
_ //跳过
n4 //ioto=3
_ //跳过
n6 //ioto=5
_ //跳过
n8 //ioto=7
_ //跳过
n10 //ioto=9
)
fmt.Println("单号:", n2, n4, n6, n8, n10)
const (
n1 = iota //ioto=0
_ //跳过
n3 //ioto=2
_ //跳过
n5 //ioto=4
_ //跳过
n7 //ioto=6
_ //跳过
n9 //ioto=8
_ //跳过
)
fmt.Println("双号:", n1, n3, n5, n7, n9)
}
//输出结果:
PS C:\Users\86186\go\src\chapter2\2.3> go run .\main.go
单号: 1 3 5 7 9
双号: 0 2 4 6 8