首頁  >  文章  >  後端開發  >  Go1.18 泛型初探

Go1.18 泛型初探

Go语言进阶学习
Go语言进阶学习轉載
2023-07-24 15:00:40863瀏覽

今天我們要實作的函數功能是:對 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中文網其他相關文章!

陳述:
本文轉載於:Go语言进阶学习。如有侵權,請聯絡admin@php.cn刪除