枚举的本质是什么,我们天天写代码用枚举,那啥是枚举啊。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.csdahua.cn/qtweb/news35/418335.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网