13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

Go中你用对枚举了么?

枚举的本质是什么,我们天天写代码用枚举,那啥是枚举啊。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.     enum week day;             // 需要加 enum 关键字
  7.     day = Wed; 
  8.     printf("%d",day);          // 输出 2
  9.     int i; 
  10.     for (i=Mon; i<=Sun; i++){  // 可以直接把枚举类型赋值给int类型
  11.       printf("%d ", i);        // 输出 0,1,2,3,4,5,6
  12.     }
  13.     return 0; 
  14. }  

上面的例子没问题,在初始化的时候,枚举值默认情况下,编译器会从分配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.     printf("%d %d %d %d %d %d %d", sunday, monday, tuesday, 
  7.             wednesday, thursday, friday, saturday); // 输出1 2 5 6 10 11 12
  8.     return 0; 

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

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

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

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

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

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

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

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

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

可以 简写成这样

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

也可以从1开始

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

或者跳过某个值

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

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

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

使用的时候

 
 
 
 
  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.")
  10. }

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

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

如果使用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.    for i := 0; i < vo.NumField(); i++ {
  11.       if typeVo.Field(i).Name == id {
  12.          return vo.Field(i).Interface().(int)
  13.       }
  14.    }
  15.    return 0
  16. }
  17. var weekdayEnum = weekday {
  18.    Monday:   1,
  19.    Tuesday:  2,
  20.    Wendsday: 3,
  21.    Thursday: 4,
  22.    Friday:   5,
  23.    Saturday: 6,
  24.    Sunday:   7
  25. }

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


网站题目:Go中你用对枚举了么?
文章分享:http://cdbrznjsb.com/article/djihjph.html

其他资讯

让你的专属顾问为你服务