Go 泛型的使用

Go 泛型的使用,第1张

Go 1.18 Beta 1版本发布泛型

2021年12月14日 Go 1.18 Beta 1版本发布,带来了大家争议已久的泛型。
已经过去几天了,今天趁周末体验了下go泛型的使用,下面给大家介绍一下,demo是官方提供的。

首先要把go的版本升级为Go 1.18 Beta 1
Administrator@20201002-163950 MINGW64 ~/Desktop
$ go get golang.org/dl/go1.18beta1@latest
go: finding golang.org/dl latest
go: downloading golang.org/dl v0.0.0-20211214194107-65ed43b8dfff
go: extracting golang.org/dl v0.0.0-20211214194107-65ed43b8dfff

Administrator@20201002-163950 MINGW64 ~/Desktop
$ go1.18beta1 download
Downloaded   0.0% (    16384 / 157362450 bytes) ...
Downloaded   5.0% (  7946192 / 157362450 bytes) ...
Downloaded  20.7% ( 32554768 / 157362450 bytes) ...
Downloaded  36.3% ( 57114192 / 157362450 bytes) ...
Downloaded  51.9% ( 81640864 / 157362450 bytes) ...
Downloaded  67.5% (106282208 / 157362450 bytes) ...
Downloaded  77.3% (121650272 / 157362450 bytes) ...
Downloaded  84.2% (132512784 / 157362450 bytes) ...
Downloaded  99.9% (157170528 / 157362450 bytes) ...
Downloaded 100.0% (157362450 / 157362450 bytes)
Unpacking C:\Users\Administrator\sdk\go1.18beta1\go1.18beta1.windows-amd64.zip ...
Success. You may now run 'go1.18beta1'

Administrator@20201002-163950 MINGW64 ~/Desktop
$ alias go=go1.18beta1

Administrator@20201002-163950 MINGW64 ~/Desktop
$ go version
go version go1.18beta1 windows/amd64
泛型初体验

SumIntsOrFloats函数:

SumIntsOrFloats这个函数有两个类型形参K和V,还有一个使用类型形参的参数,类型是map[K]V的m。函数的返回值类型是V。方括号内的K参数是什么意思呢?大家都知道map的key对类型有一定要求,所以这里K的类型参数为comparable类型,comparable是在Go中已经声明过的,这个类型是一个可以比较的类型,通俗来讲就是允许使用 == 和 !=进行值比较的类型,comparable接口满足go对map的key的要求。V类型参数也指定了一个类型约束,该约束是两种类型的联合:int64和float64,使用|指定两种类型的并集,这样就代表int64和float64都被允许作为V的实参调用这个SumIntsOrFloats函数。
指定m参数的类型为map[K]V,其中K和V是已经为类型参数指定的类型。

mian函数:

在这里调用刚才的SumIntsOrFloats函数,首先要传入类型参数,然后再传入实参,调用参数的时候按指定的类型参数将函数内的类型做替换。
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
	var s V
	for _, v := range m {
	s += v
	}
	return s
}

func main() {
	// Initialize a map for the integer values
	ints := map[string]int64{
		"first": 34,
		"second": 12,
	}

	// Initialize a map for the float values
	floats := map[string]float64{
		"first": 35.98,
		"second": 26.99,
	}

	fmt.Printf("Generic Sums111: %v and %v\n",
		SumIntsOrFloats[string, int64](ints),
		SumIntsOrFloats[string, float64](floats))
}

省略类型参数的写法

大家再来看一下下面的写法,这里调用泛型函数的时候省略了类型参数,这时编译器从函数实参的类型中推断类型参数。

func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
	var s V
	for _, v := range m {
	s += v
	}
	return s
}

func main() {
	// Initialize a map for the integer values
	ints := map[string]int64{
		"first": 34,
		"second": 12,
	}

	// Initialize a map for the float values
	floats := map[string]float64{
		"first": 35.98,
		"second": 26.99,
	}

	fmt.Printf("Generic Sums, type parameters inferred: %v and %v\n",
		SumIntsOrFloats(ints),
		SumIntsOrFloats(floats))
}
接口类型约束

官方还提供了一个更为简单的约束类型的方法,可以事先声明一种接口类型作为类型约束,这样可以事先多个函数的复用。
Number:

这个接口声明了一个int64和float64的联合,当想要类型约束为int64或float64的时候,可以直接使用这个Number类型约束,而不是再写一遍int64 | float64。

SumNumbers:

这个函数的逻辑和前面一样,但是使用的是接口类型作为类型约束,而不是联合类型。

main:

这里同样可以在调用泛型函数的时候省略类型参数
type Number interface {
	int64 | float64
}

func SumNumbers[K comparable, V Number](m map[K]V) V {
	var s V
	for _, v := range m {
		s += v
	}
	return s
}

func main() {
	// Initialize a map for the integer values
	ints := map[string]int64{
		"first": 34,
		"second": 12,
	}

	// Initialize a map for the float values
	floats := map[string]float64{
		"first": 35.01,
		"second": 26.99,
	}

	fmt.Printf("Generic Sums with Constraint: %v and %v\n",
		SumNumbers(ints),
		SumNumbers(floats))
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/990114.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存