文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go中你用对枚举了么?

2024-12-03 12:28

关注

枚举的本质是什么,我们天天写代码用枚举,那啥是枚举啊。wiki上是这么说的

用人话说就是

枚举是强类型编程语言中的一种类型,由一组名称和值组成。通常用来在编程语言中充当常量的标识符。

没毛病,我们也确实是这样使用的。比如上学的时候,经常写c的小玩具代码,c标准里面提供了enum关键字,写起来比较直白,使用的时候和struct类似,需要enum week这样写,c里面默认枚举值是从0开始,int类型,其实c里面就是把枚举当做int类型来用的。

  1. #include  
  2.    
  3. enum week{Mon, Tue, Wed, Thur, Fri, Sat, Sun};  
  4.    
  5. int main()  
  6. {  
  7.     enum week day;             // 需要加 enum 关键字 
  8.     day = Wed;  
  9.     printf("%d",day);          // 输出 2 
  10.     int i;  
  11.     for (i=Mon; i<=Sun; i++){  // 可以直接把枚举类型赋值给int类型 
  12.       printf("%d ", i);        // 输出 0,1,2,3,4,5,6 
  13.     } 
  14.     return 0;  
  15. }   

上面的例子没问题,在初始化的时候,枚举值默认情况下,编译器会从分配0开始的值,例如上面的Mon=0,Tue=1…,但是也会想不按照编译器的默认分配方式,由我自己分配,那怎么写呢,看下面的例子:

  1. #include   
  2. enum day {sunday = 1, monday, tuesday = 5,  
  3.           wednesday, thursday = 10, friday, saturday};  
  4.    
  5. int main()  
  6. {  
  7.     printf("%d %d %d %d %d %d %d", sunday, monday, tuesday,  
  8.             wednesday, thursday, friday, saturday); // 输出1 2 5 6 10 11 12 
  9.     return 0;  
  10. }  

也就是说,枚举里面可以按任何顺序将值分配给某个名称。所有未分配的名称都会把值作为前一个名称的值加一。

其实,定义几个常量的事,是不是用宏这个东西更好呢,比如这么写

  1. #define sunday  0  
  2. #define monday  1  
  3. #define tuesday 2 

但是老师说了,尽量别用宏,不是说宏不好,宏也好,编译器替换,没有运行期啥事,多快啊,但是有几个问题:

1)宏没有作用域一说 2)枚举是类型安全的

扯的有点远了,现在回来看看Go里面的枚举怎么写。当然也很简单了,官方教导我们这么写:

  1. type ByteSize float64 
  2.  
  3. const ( 
  4.     _           = iota 
  5.     KB ByteSize = 1 << (10 * iota) 
  6.     MB 
  7.     GB 

Go里面更简洁了,直接把enum关键字去掉了,其实从Go的角度看,枚举不就是常量么,搞这么多语法糖干嘛,Go里面提供了一个关键字iota可以实现常量的递增,同时也支持手动赋值,iota和手动赋值结合起来,就可以实现类似c里面的效果

  1. const ( 
  2.     A0 = iota 
  3.     A1 = iota 
  4.     A2 = iota 
  5. fmt.Println(A0, A1, A2) // "0 1 2" 

可以 简写成这样

  1. const ( 
  2.     A0 = iota 
  3.     A1 
  4.     A2 

也可以从1开始

  1. const ( 
  2.     A1 = iota + 1 
  3.     A2 
  4.     A3 
  5. fmt.Println(A1, A2, A3) // "1 2 3" 

或者跳过某个值

  1. const ( 
  2.     C1 = iota + 1 
  3.     _ 
  4.     C3 
  5.     C4 
  6. fmt.Println(C1, C3, C4) // "1 3 4" 

看到这里你或许有个疑问,这里的枚举其实就是常量么,那怎么写是字符串类型的枚举呢,你可能会说,当然是用字符串常量了。但是那只是字符串常量了,没有枚举的性质。我可能想要的是一种字符串到值的枚举类型。思考再三,看我这种写法是否可以:

  1. type Direction int 
  2.  
  3. const ( 
  4.     North Direction = iota 
  5.     East 
  6.     South 
  7.     West 
  8.  
  9. func (d Direction) String() string { 
  10.     return [...]string{"North""East""South""West"}[d] 

使用的时候

  1. var d Direction = North 
  2. fmt.Print(d) 
  3. switch d { 
  4. case North: 
  5.     fmt.Println(" goes up."
  6. case South: 
  7.     fmt.Println(" goes down."
  8. default
  9.     fmt.Println(" stays put."

当然还有一种方法,比较stupid

  1. type weekday string 
  2.  
  3. func (w weekday) isWeekday() weekday { 
  4.     return w 
  5.  
  6. type Weekday interface { 
  7.     isWeekday() weekday 
  8.  
  9. const ( 
  10.     Monday   = weekday("Monday"
  11.     Tuesday  = weekday("Tuesday"
  12.     Wendsday = weekday("Wendsday"
  13.     Thursday = weekday("Thursday"
  14.     Friday   = weekday("Friday"
  15.     Saturday = weekday("Saturday"
  16.     Sunday   = weekday("Sunday"
  17. // 使用 
  18. func main() { 
  19.     var d1 = weekday.Monday 
  20.     var d2 = weekday.Tuesday 
  21.  
  22.     fmt.Println(d1, d2, d1 == d2, d1 == weekday.Monday) 

如果使用struct表示枚举,那其实还可以使用反射的方式,比如下面这样写:

  1. import ( 
  2.    "reflect" 
  3.  
  4. type weekday struct { 
  5.    Monday, Tuesday, Wendsday, Thursday, Friday, Saturday, Sunday int 
  6.  
  7. func (c weekday) Get(id string) int { 
  8.    vo := reflect.ValueOf(c) 
  9.    typeVo := vo.Type() 
  10.  
  11.    for i := 0; i < vo.NumField(); i++ { 
  12.       if typeVo.Field(i).Name == id { 
  13.          return vo.Field(i).Interface().(int
  14.       } 
  15.    } 
  16.    return 0 
  17.  
  18. var weekdayEnum = weekday { 
  19.    Monday:   1, 
  20.    Tuesday:  2, 
  21.    Wendsday: 3, 
  22.    Thursday: 4, 
  23.    Friday:   5, 
  24.    Saturday: 6, 
  25.    Sunday:   7 

本文转载自微信公众号「码小菜」,可以通过以下二维码关注。转载本文请联系码小菜公众号。

 

来源:码小菜内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯