文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

小技巧分享:在 Go 如何实现枚举?

2024-12-03 03:44

关注

本文转载自微信公众号「脑子进煎鱼了」,作者陈煎鱼。转载本文请联系脑子进煎鱼了公众号。

大家好,我是煎鱼。

在日常的业务工程开发中,我们常常会有使用枚举值的诉求,枚举控的好,测试值边界一遍过...

有的小伙伴会说,在 Go 语言不是有 iota 类型做枚举吗,那煎鱼你这篇文章还讲什么?

讲道理,Go 语言并没有 enum 关键字,有用过 Protobuf 等的小伙伴知道,Go 语言只是 ”有限的枚举“ 支持,我们也会用常量来定义,枚举值也需要有字面意思的映射。

示例

在一些业务场景下,是没法达到我们的诉求的。示例如下:

  1. type FishType int 
  2.  
  3. const ( 
  4.  A FishType = iota 
  5.  B 
  6.  C 
  7.  D 
  8.  
  9. func main() { 
  10.  fmt.Println(A, B, C, D) 

输出结果为:“0 1 2 3”。这时候就一脸懵逼了...枚举值,应该除了键以外,还得有个对应的值。也就是这个 “0 1 2 3” 分别对应着什么含义,是不是应该输出 ”A B C D“

但 Go 语言这块就没有直接的支撑了,因此这不是一个完整的枚举类型的实现。

同时假设我们传入超过 FishType 类型声明范围的枚举值,在 Go 语言中默认也不会有任何控制,是正常输出的。

上述这种 Go 枚举实现,在某种情况下是不完全的,严格意义上不能成为 enum(枚举)。

使用 String 做枚举

如果要支持枚举值的对应输出的话,我们可以通过如下方式:

  1. type FishType int 
  2.  
  3. const ( 
  4.  A FishType = iota 
  5.  B 
  6.  C 
  7.  D 
  8.  
  9. func (f FishType) String() string { 
  10.  return [...]string{"A""B""C""D"}[f] 

运行程序:

  1. func main() { 
  2.  var f FishType = A 
  3.  fmt.Println(f) 
  4.  switch f { 
  5.  case A: 
  6.   fmt.Println("脑子进煎鱼了"
  7.  case B: 
  8.   fmt.Println("记得点赞"
  9.  default
  10.   fmt.Println("别别别..."
  11.  } 

输出结果:

  1. 脑子进煎鱼了 

我们可以借助 Go 中 String 方法的默认约定,针对于定义了 String 方法的类型,默认输出的时候会调用该方法。

这样就可以达到获得枚举值的同时,也能拿到其映射的字面意思。

自动生成 String

但每次手动编写还是比较麻烦的。在这一块,我们可以利用官方提供的 cmd/string 来快速实现。

我们安装如下命令:

  1. go install golang.org/x/tools/cmd/stringer 

在所需枚举值上设置 go:generate 指令:

  1. //go:generate stringer -type=FishType 
  2. type FishType int 

在项目根目录执行:

  1. go generate ./... 

会在根目录生成 fishtype_string.go 文件:

  1. ├── fishtype_string.go 
  2. ├── go.mod 
  3. ├── go.sum 
  4. └── main.go 

fishtype_string 文件内容:

  1. package main 
  2.  
  3. import "strconv" 
  4.  
  5. const _FishType_name = "ABCD" 
  6.  
  7. var _FishType_index = [...]uint8{0, 1, 2, 3, 4} 
  8.  
  9. func (i FishType) String() string { 
  10.  if i < 0 || i >= FishType(len(_FishType_index)-1) { 
  11.   return "FishType(" + strconv.FormatInt(int64(i), 10) + ")" 
  12.  } 
  13.  return _FishType_name[_FishType_index[i]:_FishType_index[i+1]] 

所生成出来的文件,主要是根据枚举值和映射值做了个映射,且针对超出枚举值的场景进行了判断:

  1. func main() { 
  2.  var f1 FishType = A 
  3.  fmt.Println(f1) 
  4.  var f2 FishType = E 
  5.  fmt.Println(f2) 

执行 go run . 查看程序运行结果:

  1. $ go run . 
  2. FishType(4) 

总结

在今天这篇文章中,我们介绍了如何在 Go 语言实现标准的枚举值,虽然有些繁琐,但整体不会太难。

 

也有小伙伴已经在社区中提出了 ”proposal: spec: add typed enum support“ 的提案,相信未来有机会能看到 Go 自身支持 enum(枚举)的那一天。

 

来源:脑子进煎鱼了内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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