Golang - Generics 泛型

前言

去面试发现蛮多公司会问关于 Go 的 GC 跟 GMP,和其他底层的原理
花了点时间搞懂之后技术欠债清单上的大石头又少了几个,不过还是要继续还债XD

Go 推出泛型已经有一段时间了
虽然在实际作业时程式码不会看不懂,不过要写的时候还是会卡卡的
找个时间练习一下,毕竟以前也没用过

这篇的原文是 Go 官方的泛型教学,可以在参考连结找到
更深入的实作原理跟效能测试请参考连结

什么是泛型

一般在撰写程式时,如果有同样的 function,只是实作方法不同
此时我们可以将 function 抽象化为 interface,由实际的对象来实作

泛型也是一样的概念,只是改为将 parameter 抽象化
这样就不需要撰写相同实作,只是类型不同的程式码
可以由 Go 官网教学提供的程式码来看看实际的例子
可以发现这段程式码就是需要泛型的原因
做的实作是差不多的,只有因为参数类型不同,就要多写一次

func main() {// Initialize a map for the integer valuesints := map[string]int64{"first":  34,"second": 12,}// Initialize a map for the float valuesfloats := map[string]float64{"first":  35.98,"second": 26.99,}fmt.Printf("Non-Generic Sums: %v and %v\n",SumInts(ints),SumFloats(floats))}// SumInts adds together the values of m.func SumInts(m map[string]int64) int64 {var s int64for _, v := range m {s += v}return s}// SumFloats adds together the values of m.func SumFloats(m map[string]float64) float64 {var s float64for _, v := range m {s += v}return s}

使用泛型

泛型是在 Go 1.18 以后才有的功能
泛型是在 Go 1.18 以后才有的功能
泛型是在 Go 1.18 以后才有的功能
所以版本不到是用不了的

接着来加入两段程式码来观察变化,来改良之前要重複写好几次的问题

fmt.Printf("Generic Sums: %v and %v\n",SumIntsOrFloats[string, int64](ints),SumIntsOrFloats[string, float64](floats))
// SumIntsOrFloats sums the values of map m. It supports both int64 and float64// as types for map values.func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {var s Vfor _, v := range m {s += v}return s}
如果把这段程式码放到 IDE 内会发现 SumIntsOrFloats[string, int64](ints) SumIntsOrFloats[string, float64](floats) 这两行程式码的型别宣告是多余的,可以删除,但是在没有参数的情况下还是需要宣告型别。在 [K comparable, V int64 | float64] 这段的意思是指约束函式的参数型别comparable 如果你有用 IDE 可以去找 reference 会发现说明
// any is an alias for interface{} and is equivalent to interface{} in all ways.type any = interface{}// comparable is an interface that is implemented by all comparable types// (booleans, numbers, strings, pointers, channels, arrays of comparable types,// structs whose fields are all comparable types).// The comparable interface may only be used as a type parameter constraint,// not as the type of a variable.type comparable interface{ comparable }
any 是新的保留字

简化泛型程式码

对于泛型,可以使用 interface 来宣告

type Number interface {    int64 | float64}

在原来的函式就可以改为用 interface 作为约束

// SumNumbers sums the values of map m. It supports both integers// and floats as map values.func SumNumbers[K comparable, V Number](m map[K]V) V {    var s V    for _, v := range m {        s += v    }    return s}

完成后的程式码可以在官方教学里面找到

何时适合使用泛型

https://go.dev/blog/when-generics

泛型原理以及性能

https://zhuanlan.zhihu.com/p/509290914
https://www.dolthub.com/blog/2022-04-01-fast-generics/
https://planetscale.com/blog/generics-can-make-your-go-code-slower

参考资料

https://go.dev/doc/tutorial/genericshttps://go.dev/blog/when-genericshttps://zhuanlan.zhihu.com/p/509290914https://www.dolthub.com/blog/2022-04-01-fast-generics/https://planetscale.com/blog/generics-can-make-your-go-code-slower

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章