前言
去面试发现蛮多公司会问关于 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