Go语言中没有枚举这种数据类型的,但是可以使用const配合iota模式来实现,如果要为枚举添加方法的话还涉及到类型的定义,以及为新建类型添加方法。所以在开始介绍实现go语言的枚举实现之前,我们先来看看类型别名(在Go1.9版本新增的功能,主要用于代码升级、迁移中类型的兼容性问题)和类型定义的区别。
类型别名的写法:
type TypeAlias = Type // TypeAlias只是Type的别名,本质上TypeAlias和Type是同一个类型。
类型定义的写法:
type TypeNew = Type // TypeNew 是一个新的类型,拥有Type相关的所有属性和方法
package main // 定义包名
import "fmt"
// MyInt 将MyInt 定义为int类型
type MyInt int
// IntAlias 将int 取名为IntAlias
type IntAlias = int
// 为MyInt定义一个add方法
func (a MyInt) add(b int) {
}
// 为IntAlias 定义remove方法,编译报错:cannot define new methods on non-local type int
// func (a IntAlias) remove(b int) {
// }
// 编译器提示不能在非本地类型int上定义新方法,因为type IntAlias = int只是取了一个别名,实际类型还是int类型,而int类型不再main包里,称之为非本地类型。相反的type MyInt int定义了一个新的类型MyInt,而这个类型是属于main包内的,所以支持定义方法
func main() {
// 声明MyInt 变量a
var a MyInt
// 查看变量a的类型
fmt.Printf("a type = %T\n", a)
// 声明IntAlias 变量b
var b IntAlias
// 查看变量b的类型
fmt.Printf("b type = %T\n", b)
/*
输出结果:
a type = main.MyInt
b type = int
*/
}
从上例输出结果可以得知:变量a的类型为main.MyInt,表示main包下定义的MyInt类型,而变量b的类型依然是int类型,说明IntAlias类型只会在代码中存在,编译完成时不会有IntAlias类型
另外,上例中也给大家演示了为MyInt和IntAlias类型添加方法,代码中,可以顺利的为MyInt添加方法。但是如果为IntAlias添加方法的话会报编译错误,编译器提示不能在非本地类型int上定义新方法。因为type IntAlias = int只是取了一个别名,实际类型还是int类型,而int类型不在main包里,称之为非本地类型。相反的type MyInt int定义了一个新的类型MyInt,而这个类型是定义在main包内,所以支持为其定义方法。
上面简单的和大家分享了类型别名和类型定义的区别,也和大家演示了如何为定义的类型添加方法。下面让我们学以致用,通过以上特性来实现Go语言的枚举:
package main // 定义包名
import "fmt"
// ColorType 定义一个ColorType 类型
type ColorType int
const (
// Black 使用iota进行常量值自动生成
Black ColorType = iota
// Yellow 黄色
Yellow
// Red 红色
Red
// Blue 蓝色
Blue
)
// c#的枚举有toString的功能,可以为ColorType定义toString方法实现类似的功能
func (t ColorType) toString() string {
switch t {
case Black:
return "Black"
}
return ""
}
func main() {
fmt.Println(Black, Yellow, Red, Blue)
fmt.Println(Black.toString())
}
以上示例简单的和大家演示了Go语言枚举的实现,但是toString()采用switch的方式个人感觉有点low,是否可以考虑采用Go语言的反射来简化代码呢?这个有待后续验证,目前还没去研究Go语言的反射机制。