在 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 还允许你创建泛型函数。
相关文章
在 Golang 中使用 If-Else 和 Switch Loop Inside HTML 模板
发布时间:2023/04/27 浏览次数:65 分类:Go
-
本篇文章介绍了在 Golang 的 HTML 模板中使用 if-else 和 switch 循环。因此,只要输出是 HTML,就应该始终使用 HTML 模板包而不是文本模板。
Golang 中的零值 Nil
发布时间:2023/04/27 浏览次数:166 分类:Go
-
本篇文章介绍 nil 在 Golang 中的含义,nil 是 Go 编程语言中的零值,是众所周知且重要的预定义标识符。
Golang 中的 Lambda 表达式
发布时间:2023/04/27 浏览次数:93 分类:Go
-
本篇文章介绍如何在 Golang 中创建 lambda 表达式。Lambda 表达式似乎不存在于 Golang 中。 函数文字、lambda 函数或闭包是匿名函数的另一个名称。
在 Go 中捕获 Panics
发布时间:2023/04/27 浏览次数:66 分类:Go
-
像错误一样,Panic 发生在运行时。 换句话说,当您的 Go 程序中出现意外情况导致执行终止时,就会发生 Panics。让我们看一些例子来捕捉 Golang 中的Panics。
在 Go 中使用断言
发布时间:2023/04/27 浏览次数:181 分类:Go
-
本篇文章介绍了 assert 在 GoLang 中的使用。在 Go 语言中使用断言:GoLang 不提供对断言的任何内置支持,但我们可以使用来自 Testify API 的广泛使用的第三方包断言。
Go 中的随机数生成
发布时间:2023/04/27 浏览次数:114 分类:Go
-
本篇文章介绍如何在 Go 语言中使用随机数生成功能。Go 中的随机数生成 Go 语言为随机数生成功能提供内置支持。 内置包 math 有方法 rand(),用于随机数生成。