【问题标题】:Custom string types in Go [duplicate]Go中的自定义字符串类型[重复]
【发布时间】:2020-12-24 02:25:03
【问题描述】:

如何在 Go 中创建一个仅限于特定字符串值列表的自定义类型?例如

type Suit = "Spade" | "Diamond" | "Club" | "Heart"

【问题讨论】:

    标签: go


    【解决方案1】:

    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 您可以考虑使用仅导出值的非导出类型。
    【解决方案2】:

    string 定义一个类型别名,即SuitSuit 是基础类型为字符串的类型。

    现在,创建一些 Suit 类型的常量。在下面的颂歌中,SpadeDiamondClubHeart 属于 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)
    }
    

    【讨论】:

    • 这不是您使用受限值创建数据类型的方式,正如@Abhijit_K 所说,go 不支持它。
    • this (type Suit string) 不是类型别名,类型别名具有具有特定行为的特定语法。这是一个常规类型声明golang.org/ref/spec#Type_declarations
    • @whitespace 答案中已经写了这实际上是不可能的。
    猜你喜欢
    • 2018-02-04
    • 1970-01-01
    • 2022-06-15
    • 2016-07-17
    • 2021-08-20
    • 2019-07-01
    • 1970-01-01
    • 2014-01-12
    • 2019-06-02
    相关资源
    最近更新 更多