定义常量在各个语言中都是不可或缺的语法了. 而有些语言在常量的基础上, 增加了枚举类型, 比如C
.
enum Weekday {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
};
上面的枚举, 对应的值依次为0到6.
而在Go
中, 是没有提供枚举类型的. 如果实现上面相同的功能, 难道要写成这样么?
const (
SUNDAY = 0
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
)
不过仔细想象, Go
的开发者之一就是开发C
语言的前辈, 怎么能不继承这么漂亮的语法呢?
Go
在常量定义上实现了两个特殊的特性:
- 若一个常量没有赋值, 则默认为重复上一行
- iota 神器
分别介绍一下这两个家伙.
常量的默认值
当一个常量没有明确给出值的时候, 则常量默认重复上一行赋值的行为. 比如:
const (
a = 1
b // 1
c = 2
d // 2
e, f = 3, 4
g, h // 3,4
i // 报错, 因为前一行赋值为 3,4. 无法重复
)
包括如果上一个指定了类型, 下面的也会跟着指定.
iota
为当前常量块的索引值(行号), 从0开始. 对常量块的定义, 表示包在 const() 中的常量定义. 比如:
const s = iota // 0
const o = iota // 0
const (
a = iota // 0
b // 1
c // 2
d, e = iota, iota // 3, 3
f, g // 4, 4
)
在常量定义中, iota 是可以参与运算的哦.
使用
一下举几个我想到的例子, 通过组合上面的特性, 通常还是能够有不错的效果的.
1. 定义二进制标识位
const (
isA = 1 << iota // 0b1
isB // 0b10
isC // 0b100
isD // 0b1000
)
2.丢弃及重复使用 iota
当需要索引从1开始时, 可以将第一行丢掉.
const (
_ = iota // 丢弃0
a // 1
b // 2
_ // 丢弃3
c,d = iota,iota // 4,4 重复使用
)
3.数值型运算
上面都比较简单, 想了几个玩的比较花的. 来瞅瞅.
const (
P = 3.1415926 // 定义π
P_2 = P / (2 * iota) // P/2
P_4 // P/4
P_6 // P/6
P_8 // P/8
)
const (
P = 3.1415926 // π
P_2 = P / (1 << iota) // P/2
P_4 // P/4
P_8 // P/8
P_16 // P/16
)
const (
P = 3.1415926 // 排
P_2, P_M_2 = P / (1 << iota), P * (iota + 1) // P/2 P*2
P_4, P_M_3 // P/4 P*3
P_8, P_M_4 // P/8 P*4
)
4.计算容量单位大小
const (
_ = 1 << (10 * iota) // 索引为0的数据不要了
KB // 2^10
MB // 2^20
GB // 2^30
TB // 2^40 下同
PB
EB
ZB
YB
)
OK, Go
的常量定义基本也就这些了, 如果没有iota
, 那么重复上一行行为也没有太大意义了, 毕竟定义几个相同值的常量有什么用呢? 将这两个特性想结合之后, 往往能够实现很不错的效果.