脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go语言实现枚举的示例代码

Go语言实现枚举的示例代码

2022-08-31 10:06kevinyan Golang

本文主要介绍了Go语言实现枚举的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

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

假如我们的代码里没有注释,或者等我们项目的代码里充斥着这些魔术数字的判断的时候,你是不是会很头疼?
后来我就学会了把这些状态值定义成常量,并且也搞一个判断对象状态的方法单独封装这段逻辑。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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代码变成了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 使用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 型的常量肯定不行。比如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 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 作为基础

?
1
2
3
4
5
6
7
8
type Season int
 
const (
    Summer Season = 1
    Autumn        = 2
    Winter        = 3
    Spring        = 4
)

类型创建一个别名类型,Go 里边是支持这个的

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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上的这个答案

到此这篇关于Go语言实现枚举的示例代码的文章就介绍到这了,更多相关Go语言 枚举内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7055912139357159431

延伸 · 阅读

精彩推荐
  • Golang详解Go内存模型

    详解Go内存模型

    这篇文章主要介绍了Go 内存模型的相关资料,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考...

    alenliu06219342021-02-22
  • Golang使用Golang的singleflight防止缓存击穿的方法

    使用Golang的singleflight防止缓存击穿的方法

    这篇文章主要介绍了使用Golang的singleflight防止缓存击穿的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    Chaaaaaaaaauncey5642020-06-08
  • Golanggo语言通过odbc操作Access数据库的方法

    go语言通过odbc操作Access数据库的方法

    这篇文章主要介绍了go语言通过odbc操作Access数据库的方法,实例分析了Go语言通过odbc连接、查询与关闭access数据库的技巧,需要的朋友可以参考下 ...

    work246362020-04-22
  • GolangGo语言接口的用法详解

    Go语言接口的用法详解

    本文详细讲解了Go语言接口的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    奋斗的大橙子3342022-07-13
  • Golanggo语言channel实现多核并行化运行的方法

    go语言channel实现多核并行化运行的方法

    这篇文章主要介绍了go语言channel实现多核并行化运行的方法,实例分析了channel实现多核并行化运行的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    两把刷子4222020-04-20
  • GolangGo语言中CGO的使用实践

    Go语言中CGO的使用实践

    本文主要介绍了Go语言中CGO的使用实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    mrsonko9152021-11-14
  • GolangGin与Mysql实现简单Restful风格API实战示例详解

    Gin与Mysql实现简单Restful风格API实战示例详解

    这篇文章主要为大家介绍了Gin与Mysql实现简单Restful风格API示例详解,有需要的朋友可以借鉴参考下希望能够有所帮助,祝大家多多进步...

    秋天的春13422021-12-05
  • GolangGO语言开发环境搭建过程图文详解

    GO语言开发环境搭建过程图文详解

    这篇文章主要介绍了GO语言开发环境搭建过程图文详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    给你骨质唱疏松7762021-03-27