Golang表示枚举类型的详细讲解

枚举,是一种重要的数据类型,由一组键值对组成,通常用来在编程语言中充当常量的标识符。在主流行编程语言如 c、 java 等,都有原生支持。在 go 中,大家却找不到 enum 或者其它直接用来声明枚举类型的关键字。从熟悉其它编程语言的开发者转用 go 编程,刚开始会比较难接受这种情况。其实,如果你看到如何在 go 中表示枚举类型时,可能会感受到 go 语言设计者对简洁性、问题考虑的深度,是一般资浅工程师无法比拟的。

其实,在 go 语言设计者的眼里,enum 本质是常量,为什么要多余一个关键字呢?在 go 只是没有 enum 关键字而已,其表现枚举的形式,与其它语言别无太大区别。下面来看看如果在 go 中表示枚举。

学习、使用一门语言,是学习、理解语言本身的设计哲学,同时也会感受到设计者的性格特点。

基础工作

为了下面讲解方便,这里使用 go modules 的方式先建立一个简单工程。

~/Projects/go/examples
➜  mkdir enum
~/Projects/go/examples
➜  cd enum
~/Projects/go/examples/enum
➜  go mod init enum
go: creating new go.mod: module enum
~/Projects/go/examples/enum
➜  touch enum.go 

const + iota

以 启动、运行中、停止 这三个状态为例,使用 const 关键来声明一系列的常量值。在 enum.go 中写上以下内容:

package main
import "fmt"
const (
    Running int = iota
    Pending
    Stopped
)
func main() {
    fmt.Println("State running: ", Running)
    fmt.Println("State pending: ", Pending)
    fmt.Println("State Stoped: ", Stopped)
} 

保存并运行,可以得到以下结果,

~/Projects/go/examples/enum
➜  go run enum.go
State running:  0
State pending:  1
State Stoped:  2 

在说明发生了什么之前,我们先看来一件东西,iota。相比于 c、java,go 中提供了一个常量计数器,iota,它使用在声明常量时为常量连续赋值。

比如这个例子,

const (
    a int = iota // a = 0
    b int = iota // b = 1
    c int = iota // c = 2
)
const d int = iota // d = 0 

在一个 const 声明块中,iota 的初始值为 0,每声明一个变量,自增 1。以上的代码可以简化成:

const (
    a int = iota // a = 0
    b // b = 1
    c // c = 2
)
const d int = iota // d = 0 

设想一下,如果此时有 50 或者 100 个常量数,在 c 和 java 语言中写出来会是什么情况。

关于 iota,有更多的具体的技巧(例如跳数),详细请看官方定义 iota。

通过使用 const 来定义一连串的常量,并借助 iota 常量计数器,来快速的为数值类型的常量连续赋值,非常方便。虽然没有了 enum 关键字,在这种情况下发现,是多余的,枚举本质上就是常量的组合。

当然,你可以使用以下方式,来更接近其它语言的 enum,

// enum.go
...
type State int
const (
    Running State = iota
    Pending
    Stopped
)
... 

把一组常量值,使用一个类型别名包裹起来,是不是更像其它语言中的 enum {} 定义了呢?

你还可以将上面的例子改为:

// enum.go
...
type State int
const (
    Running State = iota
    Pending
    Stopped
)
func (s State) String() string {
    switch s {
    case Running:
        return "Running"
    case Pending:
        return "Pending"
    case Stopped:
        return "Stopped"
    default:
        return "Unknown"
     }
}
... 

为定义的枚举类型加上 String 函数,运行结果如下:

~/Projects/go/examples/enum
➜  go run enum.go
State running:  Running
State pending:  Pending
State Stoped:  Stopped 

是不是很魔幻,思路一下又开阔一些,长见识了。把实际的值与打印字符分开,一般语言设计者不会想到。看到这里,有没有这种的感觉,go 语言的设计者并不是偷懒,而是为了可以偷懒想了很多、做了很多。

到此这篇关于Golang表示枚举类型的详细讲解的文章就介绍到这了,更多相关Golang 枚举类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang如何获得一个变量的类型

    直接使用reflect的TypeOf方法就可以了 fmt.Println(reflect.TypeOf(var)) 补充:golang 获取变量类型的三种方式 Using string formatting func typeof(v interface{}) string { return fmt.Sprintf("%T", v) } Using reflect package func typeof(v interface{}) string { return reflect.Ty

  • MongoDB 常用的数据类型和基本操作

    NO.1 MongoDB的常用数据类型 MongoDB中的文档类似json,我们知道,在json中,最常用的数据类型有null.bool.数组.字符串.数据.json对象等等.相对比较少,比如对于时间类型的数据,json是无法表示的,而MongoDB中对json进行了简单的优化,像json,但是又不是json.下面我们慢慢说 MongoDB的常用数据类型和MySQL比较像,你可以对比着看.它的常用数据类型有: 1.null 用于表示空值或者不存在的字段 {"x":null} 2.boo

  • Pandas数据类型之category的用法

    创建category 使用Series创建 在创建Series的同时添加dtype="category"就可以创建好category了.category分为两部分,一部分是order,一部分是字面量: In [1]: s = pd.Series(["a", "b", "c", "a"], dtype="category") In [2]: s Out[2]: 0 a 1 b 2 c 3

  • Go 第三方库之类型转换问题

    目录 01 为什么需要类型转换 02 spf13/cast 1)To_ 形式函数 2)To_E 形式函数 03 总结 强类型语言有它的优势,但也有不便利的地方,最典型的就是类型转换.Golang 作为一门强类型语言,而且不支持隐式类型转换,因此这个问题更突出.虽然 Go 提供了不少方式进行类型转换,包括相关的标准库,比如 strconv 包. 然而,strconv 包使用没那么方便,比如 "8" 转为 int 类型: s := "8" i, err := strco

  • Golang断言判断值类型的实现方法

    Golang可以通过断言,判断值的类型 s:="hello world" i:=interface{}(s)//将数值转化为interface空接口类型 //需要注意的是,必须是空接口类型才能使用断言,如果不是空接口类型会报错 //Invalid type assertion: a.(string) (non-interface type string on left) v,e:=i.(string)//返回value和error值,当err值为true则转化成功,value的值为括号

  • Golang表示枚举类型的详细讲解

    枚举,是一种重要的数据类型,由一组键值对组成,通常用来在编程语言中充当常量的标识符.在主流行编程语言如 c. java 等,都有原生支持.在 go 中,大家却找不到 enum 或者其它直接用来声明枚举类型的关键字.从熟悉其它编程语言的开发者转用 go 编程,刚开始会比较难接受这种情况.其实,如果你看到如何在 go 中表示枚举类型时,可能会感受到 go 语言设计者对简洁性.问题考虑的深度,是一般资浅工程师无法比拟的. 其实,在 go 语言设计者的眼里,enum 本质是常量,为什么要多余一个关键字呢

  • Golang设计模式之原型模式详细讲解

    目录 原型模式 概念示例 原型模式 原型是一种创建型设计模式, 使你能够复制对象, 甚至是复杂对象, 而又无需使代码依赖它们所属的类. 所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象. 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量. 概念示例 让我们尝试通过基于操作系统文件系统的示例来理解原型模式. 操作系统的文件系统是递归的: 文件夹中包含文件和文件夹, 其中又包含文件和文件夹, 以此类推. 每个文件和文件夹都可用一

  • GoLang函数栈的使用详细讲解

    目录 函数栈帧 寄存器 函数栈帧 我们的代码会被编译成机器指令并写入到可执行文件,当程序执行时,可执行文件被加载到内存,这些机器指令会被存储到虚拟地址空间中的代码段,在代码段内部,指令是低地址向高地址堆积的.堆区存储的是需要程序员手动alloc并free的空间,需要自己来控制. 虚拟内存空间是对存储器的一层抽象,是为了更好的来管理存储器,虚拟内存和存储器之间存在映射关系. 如果在一个函数中调用了另外一个函数,编译器就会对应生成一条call指令,当call指令被执行时,就会跳转到被调用函数入口处开

  • Golang详细讲解常用Http库及Gin框架的应用

    目录 1. Http标准库 1.1 http客户端 1.2 自定义请求头 1.3 检查请求重定向 1.4 http服务器性能分析 2. JSON数据处理 2.1 实体序列化 2.2 处理字段为小写下划线 2.3 省略空字段 2.4 反序列化 3. 自然语言处理 3.1 使用Map处理 3.2 定义实体处理 4. http框架 4.1 gin 4.1.1 启动服务 4.1.2 middleware 4.1.3 设置请求ID 1. Http标准库 1.1 http客户端 func main() {

  • GoLang RabbitMQ TTL与死信队列以及延迟队列详细讲解

    目录 TTL 死信队列 延迟队列 Go实现延迟队列 TTL TTL 全称 Time To Live(存活时间/过期时间).当消息到达存活时间后,还没有被消费,就会被自动清除.RabbitMQ可以设置两种过期时间: 对消息设置过期时间. 对整个队列(Queue)设置过期时间. 如何设置 设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期. 设置消息过期时间使用参数:expiration,单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这

  • GoLang并发机制探究goroutine原理详细讲解

    目录 1. 进程与线程 2. goroutine原理 3. 并发与并行 3.1 在1个逻辑处理器上运行Go程序 3.2 goroutine的停止与重新调度 3.3 在多个逻辑处理器上运行Go程序 通常程序会被编写为一个顺序执行并完成一个独立任务的代码.如果没有特别的需求,最好总是这样写代码,因为这种类型的程序通常很容易写,也很容易维护.不过也有一些情况下,并行执行多个任务会有更大的好处.一个例子是,Web 服务需要在各自独立的套接字(socket)上同时接收多个数据请求.每个套接字请求都是独立的

  • GoLang内存模型详细讲解

    目录 栈内存-协程栈-调用栈 逃逸分析 go 堆内存 堆如何进行分配 go 语言对象的垃圾回收 如何减少GC对性能的分析 GC 优化效率 栈内存-协程栈-调用栈 为什么go的栈是在堆上? go 协程栈的位置: go的协程栈位于go的堆内存,go 的gc 也是对堆上内存进行GC, go堆内存位于操作系统虚拟内存上, 记录局部变量,传递参数和返回值 ,go 使用的参数拷贝传递,如果传递的值比较大 注意传递其指针 go 参数传递 使用 值传递, 也就是说传递结构体时候,拷贝结构体的指针,传递结构体指针

  • GoLang中panic与recover函数以及defer语句超详细讲解

    目录 一.运行时恐慌panic 二.panic被引发到程序终止经历的过程 三.有意引发一个panic并让panic包含一个值 四.施加应对panic的保护措施从而避免程序崩溃 五.多条defer语句多条defer语句的执行顺序 一.运行时恐慌panic panic是一种在运行时抛出来的异常.比如"index of range". panic的详情: package main import "fmt" func main() { oneC := []int{1, 2,

  • Golang设计模式中抽象工厂模式详细讲解

    目录 抽象工厂模式 概念示例 抽象工厂模式 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类. 抽象工厂定义了用于创建不同产品的接口, 但将实际的创建工作留给了具体工厂类. 每个工厂类型都对应一个特定的产品变体. 在创建产品时, 客户端代码调用的是工厂对象的构建方法, 而不是直接调用构造函数 (new操作符). 由于一个工厂对应一种产品变体, 因此它创建的所有产品都可相互兼容. 客户端代码仅通过其抽象接口与工厂和产品进行交互. 该接口允许同一客户端代码与不同产品

  • C语言自定义类型超详细梳理之结构体 枚举 联合体

    目录 一.什么是结构体 1.结构体实现 2.匿名结构体类型 3.结构体自引用 4.结构体的内存对齐 5.结构体位段  二.什么是枚举 1.枚举类型的定义 2.枚举的优点 三.联合(共用体) 1.什么是联合(共用体) 2.联合(共用体)的定义 3.联合(共用体)的初始化 总结 一.什么是结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. //结构体声明 struct tag //struct:结构体关键字,tag:标签名,合起来是结构体类型(类型名) { memb

随机推荐