【发布时间】:2020-12-24 02:25:03
【问题描述】:
如何在 Go 中创建一个仅限于特定字符串值列表的自定义类型?例如
type Suit = "Spade" | "Diamond" | "Club" | "Heart"
【问题讨论】:
标签: go
如何在 Go 中创建一个仅限于特定字符串值列表的自定义类型?例如
type Suit = "Spade" | "Diamond" | "Club" | "Heart"
【问题讨论】:
标签: go
Go 没有代数数据类型(ADT)。你想要的是 ADT 中的“sum”类型。例如,在 Swift 和 Rust 中有枚举来支持它们。 Go 没有泛型(还没有);没有Option,也没有Result类型。
虽然可以在 Go 中使用不同的方式来实现您想要做的事情,但我更喜欢使用 const 而不是空接口或类型检查或反射。我认为 const 会更快,更易读。这就是我要走的路。如果这是你想要的,你可以从方法中返回字符串而不是打印。
package main
import "fmt"
type Suit int
const (
Spade Suit = iota + 1
Diamond
Club
Heart
)
type Card struct {
suit Suit
no int
}
func (c *Card) PrintSuit() {
switch c.suit {
case Spade:
fmt.Println("Its a Spade")
case Diamond:
fmt.Println("Its a Diamond")
case Club:
fmt.Println("Its a Club")
case Heart:
fmt.Println("Its a Heart")
default:
fmt.Println("Unknown!")
}
}
func main() {
c := Card{suit: Diamond}
c.PrintSuit()
}
如果处理逻辑是外部的,您可以在 PrintSuit 等方法中接受外部函数。
【讨论】:
Suit 值被分配一个不需要的值(例如suit = Suit(123)),但它可能是这种用例的最合适的解决方案。
iota + 1 开始,而不仅仅是iota,因为我想避免为任何西装类型赋予值0,因为这是某人使用Card{} 时的默认情况。此外,您还需要注意在 NewCard 函数中进行正确初始化,以生成正确的 Card{}。
This route doesn't do anything to prevent a Suit 您可以考虑使用仅导出值的非导出类型。
为string 定义一个类型别名,即Suit。 Suit 是基础类型为字符串的类型。
现在,创建一些 Suit 类型的常量。在下面的颂歌中,Spade、Diamond、Club、Heart 属于 Suit 类型。现在,您希望将参数限制为某些输入的函数(这是不可能的);但是你可以做些什么来限制它只接受Suit 类型,并传递任何创建的const 变量。
// Define new type alias for string
type Suit string
const (
Spade Suit = "Spade"
Diamond Suit = "Diamond"
Club Suit = "Club"
Heart Suit = "Heart"
)
// function f only accepts parameter of type "Suit"
func f(s Suit) {
fmt.Println(s)
}
func main() {
// Call the function f with Spade
f(Spade)
}
【讨论】:
type Suit string) 不是类型别名,类型别名具有具有特定行为的特定语法。这是一个常规类型声明golang.org/ref/spec#Type_declarations