今天我們要實作的函數功能是:對 map 裡所有的 value 求和。
如果沒有泛型該如何實作呢?因為value 可能會有不同的類型,例如:int64、float64 等,沒有泛型的話,針對不同類型需要透過不同的函數來實現,所以我們一般都會像下面這樣實現:
func SumInts(m map[string]int64) int64 { var s int64 for _, v := range m { s += v } return s } func SumFloats(m map[string]float64) float64 { var s float64 for _, v := range m { s += v } return s }
上面的程式碼,我們定義了兩個函數:
1、SumInts() 計算value 為int64 類型的總和;2、SumFloats() 計算value 為float64 類型的總和;
上面函數只適用於int64、float64 類型,那如果我們還想計算int、float32 等,就得把上面的函數重新copy 一份修改下類型。
這樣做豈不是稍顯麻煩,而且程式碼很臃腫,你還別說,之前標準套件有很多類似的程式碼,像是標準函式庫的Sort 套件(sort.go) 為了實現不同類型切片的排序,定義了IntSlice、Float64Slice、StringSlice。
因為之前 Go 版本不支援泛型,只能這樣實現,這也是最簡單的一種方法。
有了泛型之後,針對不同型別 int64、float64,該如何實作一個函數就能計算出 value 的總和呢?
這一小節我們透過一個泛型函數實作既可以接收value 為int64 類型的map 作為參數,也可以接收value 為float64 類型的map 作為參數。
完整程式碼如下:
func Sum[K comparable, V int64 | float64](m map[K]V "K comparable, V int64 | float64") V { var s V for _, v := range m { s += v } return s } func main() { ints := map[string]int64{ "first": 1, "second": 2, } fmt.Println(Sum[string, int64](ints "string, int64")) floats := map[string]float64{ "first": 35.98, "second": 26.99, } fmt.Println(Sum[string, float64](floats "string, float64")) }
上面的程式碼,我們定義了Sum() 函數,它是一個泛型函數,可以看到與普通函數不同的是,在函數名稱與函數參數列表之間有一組方括號[],方括號裡有兩個參數K 和V,Go 語言稱為型別參數,緊接在K、V 後面是型別限制,其中comparable 是Go 語言預先宣告的,表示任何能做== 和!= 操作的型別。 V 的型別限制是 int64、float64 其中的一種。函數參數是 m,型別是 map[K]V,回傳型別是 V。
呼叫函數也與呼叫普通函數有點不同,在函數名稱與實參之間有一組方括號 [],指明了類型名稱。例如第一次呼叫 Sum() 函數時,型別名稱分別是 string、int64,那麼在執行函數時,對應 K、V 的型別分別是 string 和 int64。
第二次调用该 Sum() 函数时,K、V 的类型分别是 string 和 float64。
通过泛型编程,我们就可以实现一个函数处理多种数据类型。
执行上面的代码输出:
3 62.97
以上是Go1.18 泛型初探的詳細內容。更多資訊請關注PHP中文網其他相關文章!