在Go中,没有 enum 的数据类型,如C++、Java或Python语言。然而,这并不意味着 enums 不能被创建。如果你声明自定义类型的常量和一些辅助方法,你会得到一个非常类似于 enum 在其他编程语言中。
请看下面的例子,看看如何在Go中声明 enum 在Go中。
在这个例子中,我们用
iota来声明常量。
package main
import (
"fmt"
)
type Season int
const (
Spring Season = iota + 1
Summer
Autumn
Winter
)
func (s Season) String() string {
seasons := [...]string{"spring", "summer", "autumn", "winter"}
if s < Spring || s > Winter {
return fmt.Sprintf("Season(%d)", int(s))
}
return seasons[s-1]
}
func (s Season) IsValid() bool {
switch s {
case Spring, Summer, Autumn, Winter:
return true
}
return false
}
func main() {
mySeasons := []Season{Spring, Summer, Autumn, Winter, 6}
for _, s := range mySeasons {
fmt.Printf("season: %s, is valid: %t\n", s, s.IsValid())
}
}
输出
season: spring, is valid: true
season: summer, is valid: true
season: autumn, is valid: true
season: winter, is valid: true
season: Season(6), is valid: false
它是如何工作的
-
声明我们的
enum的自定义类型和元素type Season int const ( Spring Season = iota + 1 Summer Autumn Winter )作为第一步,我们声明新的整数类型
Season,并使用关键字创建连续的常量值。iota关键字创建连续的常量值。为什么我们使用int类型而不是字符串?
常量通常被用来与一个变量相比较,比如说
if Spring != season { // do something }通常我们不需要它们的具体数值,只需要知道常量和变量是不同的这一事实。在这种情况下,比较两个
int值要比比较两个字符串快。int类型的常量也占用较少的内存空间。为什么我们要声明自定义类型
Season,而不是使用无类型的常量?自定义类型可以防止在编译阶段就传递无效的值。如果我们将季节声明为非类型常量,下面将无效的季节值6分配给变量的代码将无任何错误地执行。
var d int = 6 season := Spring season = d当使用
Season类型时,为了使这段代码无任何错误地运行,你需要明确地转换d变量,所以不可能意外地做到这一点。var d int = 6 season := Spring season = Season(d)另外,自定义类型的 **
enum**使得代码更加简洁。例如,在声明函数func foo(s Season)你马上就可以看到,该函数需要季节作为参数,在
func foo(s int)你只知道它需要一个整数参数,没有任何语义。多亏了自定义类型,我们还可以将方法添加到
enum元素添加方法,比如String()和IsValid()。 -
创建
String()方法func (s Season) String() string { seasons := [...]string{"spring", "summer", "autumn", "winter"} if s < Spring || s > Winter { return fmt.Sprintf("Season(%d)", int(s)) } return seasons[s-1] }String()方法增加了将 常量打印为 ,而不是 ,所以对于语句 ,我们得到 ,而不是 。对于范围之外的变量 ,我们打印 ,其中 是 类型变量的整数值。Seasonstringintfmt.Println(Spring)spring1Spring..WinterSeason(X)XSeason -
创建
IsValid()方法func (s Season) IsValid() bool { switch s { case Spring, Summer, Autumn, Winter: return true } return false }IsValid()是一个辅助方法。这个函数应该总是在用户输入时被调用,以验证用户没有传递一个无效的值。SeasonSpringSummerAutumnWinterenum. -
main()功能func main() { mySeasons := []Season{Spring, Summer, Autumn, Winter, 6} for _, s := range mySeasons { fmt.Printf("season: %s, is valid: %t\n", s, s.IsValid()) } }main()函数呈现了当你使用String()和IsValid()方法来处理Season常量的定义值以及超出范围的值时,你会得到什么。