如何在Go中使用泛型
引言
在Go 1.18中,该语言引入了一个名为泛型类型(通常简称为泛型)的新功能,它已经在Go开发人员的愿望清单上存在一段时间了。在编程中,泛型类型是一种可以与多种其他类型结合使用的类型。通常在Go中,如果您希望能够对同一个变量使用两种不同类型,则需要使用特定的接口,例如io.Reader
,或者使用允许使用任何值的[interface{}
]。然而,使用interface{}
会使处理这些类型变得具有挑战性,因为你需要在几个其他潜在类型之间进行转换才能与它们交互。使用泛型类型可以让你直接与类型交互,从而得到更清晰、更易于阅读的代码。
在本教程中,你将创建一个与一副扑克牌交互的程序。你将首先创建一个deck对象,使用interface{}
来与扑克牌交互,然后更新它以使用泛型类型。在这些更新之后,将使用泛型在deck中添加第二种card类型,然后更新deck,将其泛型类型限制为只支持card类型。最后,您将创建一个函数,使用您的card并支持泛型类型。
没有泛型的Go集合
Go的一个强大功能是它能够使用接口灵活地表示多种类型。许多用Go编写的代码仅使用提供的功能接口就可以很好地工作。这就是Go长期不支持泛型的原因之一。
在本教程中,您将创建一个Go程序,模拟从Deck
牌中随机获取PlayingCard
。在本节中,你将使用interface{}
来允许Deck
与任何类型的牌进行交互。在本教程的后面,你将更新程序以使用泛型,这样你就可以更好地理解它们之间的差异,并识别出哪种方法更好。
编程语言中的类型系统通常可以分为两个不同的类别:类型检查和类型检查。语言可以使用强或弱类型,以及静态或动态类型检查。有些语言混合使用它们,但Go非常适合强类型和静态检查的语言。强类型意味着Go确保变量中的值与变量的类型匹配,因此例如,你不能将int
值存储在string
变量中。作为一个静态检查类型系统,Go的编译器将在编译程序时检查这些类型规则,而不是在程序运行时。
使用像Go这样的强类型、静态检查语言的一个好处是,编译器在程序发布之前让您知道任何潜在的错误,避免某些“无效类型”的运行时错误。然而,这确实给Go程序增加了一个限制,因为您必须在编译程序之前知道您打算使用的类型。一种处理方法是使用interface{}
类型。interface{}
类型适用于任何值的原因是它没有为接口定义任何必需的方法(由空的{}
表示),因此任何类型都可以匹配接口。
要开始使用interface{}
来创建你的程序来表示你的卡片,你需要一个目录来保存程序的目录。在本教程中,你将使用一个名为projects
的目录。
首先,创建projects
目录并导航到它:
mkdir projects
cd projects
接下来,创建项目目录并导航到它。在这种情况下,使用目录generics
:
mkdir generics
cd generics
在generics
目录下,使用nano
或者你最喜欢的编辑器来打开main.go
文件:
nano main.go
在main.go
文件中,首先添加你的package
声明并import
你需要的包:
main.go
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
package main
声明让Go将你的程序编译为二进制文件,以便你可以直接运行它,而import
语句告诉Go你将在后面的代码中使用哪些包。
现在,定义你的PlayingCard
类型及其相关的函数和方法:
main.go
...
type PlayingCard struct {
Suit string
Rank string
}
func NewPlayingCard(suit string, card string) *PlayingCard {
return &PlayingCard{
Suit: suit, Rank: card}
}
func (pc *PlayingCard) String() string {
return fmt.Sprintf("%s of %s", pc.Rank, pc.Suit)
}
在这个代码片段中,我们定义了一个名为PlayingCard
的结构体,它具有Suit
和Rank
属性,用来表示一副52张扑克牌中的所有牌。Suit可以是方块(Diamonds)、红心(Hearts)、梅花(Clubs)或黑桃(spade), Rank (Rank)可以是A
, 2
, 3
,以此类推直到K
。
我们还定义了一个NewPlayingCard
函数作为PlayingCard
结构体的构造函数,以及一个
String方法,它将使用
fmt.Sprintf`返回扑克牌的rank和花色。
接下来,使用AddCard
和RandomCard
方法创建你的Deck
类型,以及NewPlayingCardDeck
函数来创建一个包含所有52张扑克牌的*Deck
:
main.go
...
type Deck struct {
cards []interface{
}
}
func NewPlayingCardDeck() *Deck {
suits := []string{
"Diamonds", "Hearts", "Clubs", "Spades"}
ranks := []string{
"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
deck := &Deck{
}
for _, suit := range suits {
for _, rank := range ranks {
deck.AddCard(NewPlayingCard(suit, rank))
}
}
return deck
}
func (d *Deck) AddCard(card interface{
}) {
d.cards = append(d.cards, card)
}
func (d *Deck) RandomCard() interface{
} {
r := rand.New(rand.NewSource(time.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!