Web前端培训_Web前端实战培训【立即报名】-php中文网Web前端第二期
作者信息

青灯夜游

今天学习一小步,明天提升一大步

最近文章
php怎么修改数组中的内容854
php如何比较两个数组是否相等489
推荐视频教程
  • Go语言教程手册Go语言教程手册
  • Go编程基础视频教程Go编程基础视频教程
  • Go参考手册Go参考手册
  • Go 中文开发手册Go 中文开发手册
  • go语言基础与基本函数go语言基础与基本函数
  • 视频教程分类
    首页 >后端开发 >Golang > 正文

    浅析Golang中怎么实现枚举(附代码)

    转载2022-02-04 09:00:3101618
    Golang中怎么实现枚举?下面本篇文章给大家介绍一下Golang中实现枚举的方法,希望对大家有所帮助!

    在编程领域里,枚举用来表示只包含有限数量的固定值的类型,在开发中一般用于标识错误码或者状态机。拿一个实体对象的状态机来说,它通常与这个对象在数据库里对应记录的标识状态的字段值相对应。【相关推荐:Go视频教程

    在刚开始学编程的时候,你一定写过,至少见过直接使用魔术数字进行判断的代码。啥叫魔术数字呢,举个例子,要置顶一个文章的时候先判断文章是不是已发布状态。

    if (article.state == 2) {
       // state 2 代表文章已发布
    }

    假如我们的代码里没有注释,或者等我们项目的代码里充斥着这些魔术数字的判断的时候,你是不是会很头疼?

    后来我就学会了把这些状态值定义成常量,并且也搞一个判断对象状态的方法单独封装这段逻辑。

    public class ArticleState {
        
        public static final int Draft = 1; //草稿
        
        public static final int Published = 2; //发布
        
        public static final int Deleted = 3; // 已删除
    }
    
    public  Boolean checkArticleState(int state) {
        
        ...
        
    }

    这种用法,肯定是比在程序里直接用魔术数字进行判断要强很多啦,至少看着不会很头疼,不会想骂**。

    不过后来被当时带我的老大哥说这种也有缺点,上面这个 checkArticleState 方法用来检查文章状态,本意是让调用者传入 ArticleState 的三个静态常量之一,但由于没有类型上的约束,因此传入任意一个 int 值在语法上也是允许的,编译器也不会提出任何警告,用枚举更合适一些。

    em~! 我不记得大学教 Java 的那个学期老师讲过这玩意啊,莫非又是一个上课玩手机错过的知识点?所以使用枚举后我们的Java代码变成了:

    // 使用enum而非class声明
    public enum ArticleState {
    	
        //要在enum里创建所有的枚举对象
        Draft(1, "草稿");
        Published(2, "已发布");
        Deleted(3, "已删除")
          
        // 自定义属性
        private int code;
    
        private String text;
      
        // 构造方法必须是private的
        ArticleState(int code, String text) {
            this.code = id;
            this.text = name;
        }
    }
    
    public  Boolean checkArticleState(ArticleState state) {
        
        ...
        
    }

    这样就能靠形参的枚举类型帮我们过滤掉非法的状态值,把整型值作为参数传给 checkArticleState 方法时因为类型不匹配编译不过去,在写代码是编译器也能马上提示出来。

    如果没有用过 Java 的小伙伴也不用纠结,主要语法点我用注释标注出来了,大家应该都能看懂。

    后来这两年主要在用Go做项目,我发现相似的问题 Go 里存在,但是 Go 并没有提供枚举类型,那怎么做到进行状态值的正确限制呢?如果还是用 int 型的常量肯定不行。比如:

     const (
         Draft int = 1
         Published = 2
         Deleted   = 3
     )
    
     const (
         Summer int = 1
         Autumn     = 2
         Winter     = 3
         Spring     = 4
     )
    
     func main() {
         // 输出 true, 不会有任何编译错误
         fmt.Println(Autumn == Draft)
     }

    比如上面定义了两组 int 类型的常量,一类代表文章状态,一类代表季节的四季。这种方式拿文章状态与季节进行比较不会有任何编译上的错误。

    答案在 Go 内置库或者一些咱们都知道的开源库的代码里就能找到。比如看看 google.golang.org/grpc/codes 里的gRPC 的错误码是怎么定义的,就能明白该怎么正确的实现枚举。

    我们可以用 int 作为基础类型创建一个别名类型,Go 里边是支持这个的

    type Season int
    
    const (
    	Summer Season = 1
    	Autumn        = 2
    	Winter        = 3
    	Spring        = 4
    )

    当然定义连续的常量值的时候 Go 里边经常使用 iota,所以上面的定义还能进一步简化。

    type Season int
    
    const (
    	Summer Season = iota + 1
    	Autumn
    	Winter
    	Spring
    )
    
    type ArticleState int
    
    const (
      Draft int = iota + 1
      Published
      Deleted  
    )
    
    func checkArticleState(state ArticleState) bool {
    	// ... 
    }
    
     func main() {
       // 两个操作数类型不匹配,编译错误
       fmt.Println(Autumn == Draft)
    	// 参数类型不匹配,但是因为 ArticleState 底层的类型是 int 所以传递 int 的时候会发生隐式类型转换,所以不会报错
       checkArticleState(100)
     }

    虽然这些状态值的底层的类型都是 int 值,但是现在进行两个不相干类型的枚举值比较,会造成编译错误,因为现在我们使用状态值的地方都有了类型限制。

    不过函数 checkArticleState 的参数类型设置成了 ArticleState 但是因为 ArticleState 底层的类型是 int 。所以调用 checkArticleState 时传递 int 类型的参数会发生隐式类型转换,不会造成编译报错,这块如果想解决,只能重新定义类型来实现了,

    可以参考StackOverflow上的这个答案:

    https://stackoverflow.com/questions/50826100/how-to-disable-implicit-type-conversion-for-constants

    更多编程相关知识,请访问:编程视频!!

    以上就是浅析Golang中怎么实现枚举(附代码)的详细内容,更多请关注php中文网其它相关文章!

    Web大前端开发直播班

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除

  • 相关标签:Golang 枚举
  • 相关文章

    相关视频


    网友评论

    文明上网理性发言,请遵守 新闻评论服务协议

    我要评论
  • 专题推荐