在 Go 中如何使用泛型 入门 – 限制泛型类型

通常,我们不希望或不需要对泛型使用的类型进行任何限制,因为我们不一定关心特定数据。 但是,其他时候,我们需要能够限制泛型使用的类型。 例如,如果我们正在创建一个泛型 Sorter 类型,则可能希望将其泛型类型限制为具有 Compare 方法的类型,以便 Sorter 可以比较它所持有的项目。 如果不包括该限制,则这些值甚至可能没有 Compare 方法,并且我们的 Sorter 将不知道如何比较它们。

在本节中,我们将为卡片创建一个新的 Card 接口,然后更新我们的 Deck 以仅允许添加卡片类型。

要开始更新,请打开 main.go 文件并添加 Card 接口:

import (
...
)

type Card interface {
    fmt.Stringer

    Name() string
}

我们的 Card 接口的定义与过去可能使用的任何其他 Go 接口相同; 将其与泛型一起使用没有特殊要求。 在此 Card 接口中,要想被视为 Card,它必须实现 fmt.Stringer 类型(它必须具有 Card 已有的 String 方法),并且它还必须具有返回 a 字符串值。

接下来,更新我们的 TradingCard 和 PlayingCard 类型以添加新的 Name 方法,除了现有的 String 方法,因此它们实现 Card 接口:

...

type TradingCard struct {
    ...
}

...

func (tc *TradingCard) Name() string {
    return tc.String()
}

...

type PlayingCard struct {
    ...
}

...

func (pc *PlayingCard) Name() string {
    return pc.String()
}

TradingCard 和 PlayingCard 已经有实现 fmt.Stringer 接口的 String 方法。 所以要实现 Card 接口,只需要添加新的 Name 方法即可。 另外,由于 fmt.Stringer 已经实现了返回卡片的名称,您可以只返回 Name 的 String 方法的结果。

现在,更新我们的 Deck,使其仅允许将 Card 类型用于 C:

...

type Deck[C Card] struct {
    cards []C
}

在此更新之前,我们有 C any 用于类型限制(称为类型约束),这并不是什么限制。 由于 any 与 interface{} 的含义相同,因此它允许将 Go 中的任何类型用于 C 类型参数。 现在我们已经用新的 Card 接口替换了 any,Go 编译器将确保在编译程序时用于 C 的任何类型都实现 Card。

由于我们添加了此限制,现在可以在我们的 Deck 类型的方法中使用 Card 提供的任何方法。 如果我们希望 RandomCard 也打印出正在绘制的卡片的名称,它可以访问 Name 方法,因为它是 Card 接口的一部分。 我们将在下一篇文章中看到这一点。

这几个更新是需要进行的唯一更新,以将我们的 Deck 类型限制为仅使用 Card 值。 保存更改后,使用 go run 运行更新的程序:

$ go run main.go

输出的结果如下

--- drawing playing card ---
drew card: 5 of Clubs
card suit: Clubs
card rank: 5
--- drawing trading card ---
drew card: Droplets
card collectable name: Droplets

我们会看到,除了选择不同的卡之外,输出并没有改变。 由于我们的更新仅将值限制为已经使用的类型,因此程序的功能没有改变。

在本篇文章中,我们添加了新的 Card 接口并更新了 TradingCard 和 PlayingCard 来实现该接口。 还更新了 Deck 的类型约束以将其类型参数限制为仅实现 Card 接口的类型。

不过,到目前为止,我们只创建了一个通用结构类型。 除了创建泛型类型,Go 还允许你创建泛型函数。

免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » 在 Go 中如何使用泛型 入门 – 限制泛型类型