如何在Go中使用泛型

2023-12-25 13:00:40

引言

在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的结构体,它具有SuitRank属性,用来表示一副52张扑克牌中的所有牌。Suit可以是方块(Diamonds)、红心(Hearts)、梅花(Clubs)或黑桃(spade), Rank (Rank)可以是A23,以此类推直到K

我们还定义了一个NewPlayingCard函数作为PlayingCard结构体的构造函数,以及一个String方法,它将使用fmt.Sprintf`返回扑克牌的rank和花色。

接下来,使用AddCardRandomCard方法创建你的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.

文章来源:https://blog.csdn.net/QIU176161650/article/details/135193783
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。