枚举的本质是什么,我们天天写代码用枚举,那啥是枚举啊。wiki上是这么说的
用人话说就是
枚举是强类型编程语言中的一种类型,由一组名称和值组成。通常用来在编程语言中充当常量的标识符。
没毛病,我们也确实是这样使用的。比如上学的时候,经常写c的小玩具代码,c标准里面提供了enum关键字,写起来比较直白,使用的时候和struct类似,需要enum week这样写,c里面默认枚举值是从0开始,int类型,其实c里面就是把枚举当做int类型来用的。
- #include
- enum week{Mon, Tue, Wed, Thur, Fri, Sat, Sun};
- int main()
- {
- enum week day; // 需要加 enum 关键字
- day = Wed;
- printf("%d",day); // 输出 2
- int i;
- for (i=Mon; i<=Sun; i++){ // 可以直接把枚举类型赋值给int类型
- printf("%d ", i); // 输出 0,1,2,3,4,5,6
- }
- return 0;
- }
上面的例子没问题,在初始化的时候,枚举值默认情况下,编译器会从分配0开始的值,例如上面的Mon=0,Tue=1…,但是也会想不按照编译器的默认分配方式,由我自己分配,那怎么写呢,看下面的例子:
- #include
- enum day {sunday = 1, monday, tuesday = 5,
- wednesday, thursday = 10, friday, saturday};
- int main()
- {
- printf("%d %d %d %d %d %d %d", sunday, monday, tuesday,
- wednesday, thursday, friday, saturday); // 输出1 2 5 6 10 11 12
- return 0;
- }
也就是说,枚举里面可以按任何顺序将值分配给某个名称。所有未分配的名称都会把值作为前一个名称的值加一。
其实,定义几个常量的事,是不是用宏这个东西更好呢,比如这么写
- #define sunday 0
- #define monday 1
- #define tuesday 2
但是老师说了,尽量别用宏,不是说宏不好,宏也好,编译器替换,没有运行期啥事,多快啊,但是有几个问题:
1)宏没有作用域一说 2)枚举是类型安全的
扯的有点远了,现在回来看看Go里面的枚举怎么写。当然也很简单了,官方教导我们这么写:
- type ByteSize float64
- const (
- _ = iota
- KB ByteSize = 1 << (10 * iota)
- MB
- GB
- )
Go里面更简洁了,直接把enum关键字去掉了,其实从Go的角度看,枚举不就是常量么,搞这么多语法糖干嘛,Go里面提供了一个关键字iota可以实现常量的递增,同时也支持手动赋值,iota和手动赋值结合起来,就可以实现类似c里面的效果
- const (
- A0 = iota
- A1 = iota
- A2 = iota
- )
- fmt.Println(A0, A1, A2) // "0 1 2"
可以 简写成这样
- const (
- A0 = iota
- A1
- A2
- )
也可以从1开始
- const (
- A1 = iota + 1
- A2
- A3
- )
- fmt.Println(A1, A2, A3) // "1 2 3"
或者跳过某个值
- const (
- C1 = iota + 1
- _
- C3
- C4
- )
- fmt.Println(C1, C3, C4) // "1 3 4"
看到这里你或许有个疑问,这里的枚举其实就是常量么,那怎么写是字符串类型的枚举呢,你可能会说,当然是用字符串常量了。但是那只是字符串常量了,没有枚举的性质。我可能想要的是一种字符串到值的枚举类型。思考再三,看我这种写法是否可以:
- type Direction int
- const (
- North Direction = iota
- East
- South
- West
- )
- func (d Direction) String() string {
- return [...]string{"North", "East", "South", "West"}[d]
- }
使用的时候
- var d Direction = North
- fmt.Print(d)
- switch d {
- case North:
- fmt.Println(" goes up.")
- case South:
- fmt.Println(" goes down.")
- default:
- fmt.Println(" stays put.")
- }
当然还有一种方法,比较stupid
- type weekday string
- func (w weekday) isWeekday() weekday {
- return w
- }
- type Weekday interface {
- isWeekday() weekday
- }
- const (
- Monday = weekday("Monday")
- Tuesday = weekday("Tuesday")
- Wendsday = weekday("Wendsday")
- Thursday = weekday("Thursday")
- Friday = weekday("Friday")
- Saturday = weekday("Saturday")
- Sunday = weekday("Sunday")
- )
- // 使用
- func main() {
- var d1 = weekday.Monday
- var d2 = weekday.Tuesday
- fmt.Println(d1, d2, d1 == d2, d1 == weekday.Monday)
- }
如果使用struct表示枚举,那其实还可以使用反射的方式,比如下面这样写:
- import (
- "reflect"
- )
- type weekday struct {
- Monday, Tuesday, Wendsday, Thursday, Friday, Saturday, Sunday int
- }
- func (c weekday) Get(id string) int {
- vo := reflect.ValueOf(c)
- typeVo := vo.Type()
- for i := 0; i < vo.NumField(); i++ {
- if typeVo.Field(i).Name == id {
- return vo.Field(i).Interface().(int)
- }
- }
- return 0
- }
- var weekdayEnum = weekday {
- Monday: 1,
- Tuesday: 2,
- Wendsday: 3,
- Thursday: 4,
- Friday: 5,
- Saturday: 6,
- Sunday: 7
- }
本文转载自微信公众号「码小菜」,可以通过以下二维码关注。转载本文请联系码小菜公众号。
分享名称:Go中你用对枚举了么?
标题网址:http://www.shufengxianlan.com/qtweb/news35/418335.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联