Golang泛型的使用方法詳解
Go 和Python語言不同,處理不同數(shù)據(jù)類型非常嚴(yán)格。如Python可以定義函數(shù)帶兩個(gè)數(shù)值類型并返回較大的數(shù)值,但可以不嚴(yán)格指定參數(shù)類型為float或integer。同樣功能go1.18之前版本需要定義兩個(gè)函數(shù)分別處理對(duì)應(yīng)類型,通過泛型可以實(shí)現(xiàn)上面描述功能,無需為每種類型重復(fù)定義函數(shù)。
本文通過示例學(xué)習(xí)Go泛型,包括三個(gè)部分:非泛型函數(shù),泛型函數(shù),泛型類型約束。
泛型的作用
我們知道Go一些函數(shù)(如fmt.Println)使用空interface支持多種數(shù)據(jù)類型,但需要開發(fā)者寫大量代碼實(shí)現(xiàn)很多函數(shù)或方法支持多種自定義類型不是最佳選項(xiàng),于是泛型登場(chǎng),提供新的解決方案,無需使用接口和反射支持多種數(shù)據(jù)類型。
下面通過示例來說明:
package main
import (
"fmt"
)
func Print[T any](s []T) {
for _, v := range s {
fmt.Print(v, " ")
}
fmt.Println()
}
func main() {
Ints := []int{1, 2, 3}
Strings := []string{"One", "Two", "Three"}
Print(Ints)
Print(Strings)
}
上面代碼種Print()函數(shù)使用泛型,通過在函數(shù)名稱和參數(shù)之間增加[T any]指定泛型變量, 既然T 為any類型,函數(shù)可傳入任何數(shù)據(jù)類型slice。當(dāng)然Print函數(shù)不能處理slice之外的輸入,這是因?yàn)楹瘮?shù)實(shí)現(xiàn)決定的。通過泛型函數(shù)可以避免針對(duì)每種數(shù)據(jù)類型編寫函數(shù),這種通用的思想就是泛型。
非泛型函數(shù)
我們實(shí)現(xiàn)兩個(gè)函數(shù),返回?cái)?shù)值類型數(shù)組元素的和。我們至少創(chuàng)建兩個(gè)函數(shù),一個(gè)針對(duì)float64類型,另一個(gè)為int64,因此工作量翻倍。
package main
import "fmt"
func main() {
f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
i := []int64{1, 2, 3, 4, 5}
s1 := SumOfFloat(f)
s2 := SumOfIntegers(i)
fmt.Println("Sum for float64 :", s1)
fmt.Println("Sum for int64 :", s2)
}
func SumOfFloat(nums []float64) float64 {
var sum float64
for _, num := range nums {
sum += num
}
return sum
}
func SumOfIntegers(nums []int64) int64 {
var sum int64
for _, num := range nums {
sum += num
}
return sum
}
運(yùn)行輸出結(jié)果:
$ go run main.go
Sum for float64 : 15
Sum for int64 : 15
上面代碼針對(duì)兩種類型定義了兩個(gè)函數(shù),返回各自參數(shù)對(duì)應(yīng)類型數(shù)組元素之和。下面通過泛型合并兩個(gè)函數(shù)為一個(gè),節(jié)約時(shí)間和精力。
泛型函數(shù)
本節(jié)實(shí)現(xiàn)單個(gè)函數(shù),參數(shù)仍然是數(shù)組,但類型可以為float64或int64,并返回?cái)?shù)組元素之和,從而可以代替上面兩個(gè)函數(shù)。
為了能夠定義函數(shù)接收float64和int64兩種類型,新的泛型函數(shù)需要聲明接收的類型,即調(diào)用代碼需要判斷類型是否為float64或int64。為此,新的函數(shù)簽名需要有點(diǎn)變化,除了普通的參數(shù)外,還需要聲明類型參數(shù),從而轉(zhuǎn)換函數(shù)為泛型函數(shù)支持不同類型。
每個(gè)形參都有一個(gè)類型約束,它指定調(diào)用代碼可用于形參允許的實(shí)參類型。在編譯時(shí)這些參數(shù)表示的類型就是調(diào)用代碼支持的類型。當(dāng)然泛型函數(shù)的實(shí)現(xiàn)邏輯需要支持形參聲明的所有類型。舉例,泛型函數(shù)支持字符串和數(shù)值參數(shù),函數(shù)實(shí)現(xiàn)邏輯需要對(duì)參數(shù)進(jìn)行索引,顯然數(shù)值無法索引將引起編譯錯(cuò)誤。
泛型函數(shù)語法:
func genericFunction[T any](s []T) []T{
}
解釋如下:
上面語法種在名稱和參數(shù)之間的[]用于指定形式參數(shù)類型,可以是一組類型或一個(gè)約束接口。T 參數(shù)類型,用于定義形式參數(shù)和返回值類型。
函數(shù)內(nèi)部也可以訪問參數(shù),any 是一個(gè)interface,T必須實(shí)現(xiàn)該接口。Go1.18版本引入any,底層引用空接口,即interface{}。 下面舉例說明:
package main
import "fmt"
func main() {
f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
i := []int64{1, 2, 3, 4, 5}
s1 := genericSum(f)
s2 := genericSum(i)
fmt.Println("Sum for float64 :", s1)
fmt.Println("Sum for int64 :", s2)
}
func genericSum[N int64 | float64](nums []N) N {
var sum N
for _, num := range nums {
sum += num
}
return sum
}
輸出結(jié)果:
$ go run main.go
Sum for float64 : 15
Sum for int64 : 15
上面示例中演示定義泛型函數(shù)genericSum。參數(shù)類型在[]中聲明的泛型類型。N聲明在形參和返回值中使用,N是新的類型,被限定了兩種類型float64 和 int64的聯(lián)合類型。
在函數(shù)體類,首先聲明N類型變量,然后遍歷數(shù)組計(jì)算綜合并返回。
假設(shè)泛型函數(shù)支持很多種類型,比如:int, int8 , int26, int32, int64, float32, float64。這樣函數(shù)簽名變得非常冗長難看,我們可以定義一個(gè)類型包括上述類型,本質(zhì)上就是把聯(lián)合類型遷移至函數(shù)聲明外面。
package main
import "fmt"
type Number interface {
int64 | float64
}
func main() {
f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
i := []int64{1, 2, 3, 4, 5}
s1 := genericSum(f)
s2 := genericSum(i)
fmt.Println("Sum for float64 :", s1)
fmt.Println("Sum for int64 :", s2)
}
func genericSum[N Number](nums []N) N {
var sum N
for _, num := range nums {
sum += num
}
return sum
}
總結(jié)
本文是關(guān)于Go泛型的,因?yàn)榉盒褪荊olang的新成員。通過對(duì)比帶泛型和不帶泛型的函數(shù),泛型可以很明顯地節(jié)省時(shí)間和精力。泛型不是接口的替代品,兩者被設(shè)計(jì)為一起工作,避免重復(fù)代碼,讓Go類型更安全、代碼更整潔。
到此這篇關(guān)于Golang泛型的使用方法詳解的文章就介紹到這了,更多相關(guān)Golang泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用client-go工具調(diào)用kubernetes API接口的教程詳解(v1.17版本)
這篇文章主要介紹了使用client-go工具調(diào)kubernetes API接口(v1.17版本),本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08
golang?Gin上傳文件返回前端及中間件實(shí)現(xiàn)示例
這篇文章主要為大家介紹了golang?Gin上傳文件返回前端及中間件實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
Go實(shí)現(xiàn)mongodb增刪改查工具類的代碼示例
這篇文章主要給大家介紹了關(guān)于Go實(shí)現(xiàn)mongodb增刪改查工具類的相關(guān)資料,MongoDB是一個(gè)NoSQL數(shù)據(jù)庫,它提供了靈活的文檔存儲(chǔ)模型以及強(qiáng)大的查詢和操作功能,需要的朋友可以參考下2023-10-10
Golang中g(shù)oto跳轉(zhuǎn)語句的實(shí)現(xiàn)
本文主要介紹了Golang中g(shù)oto跳轉(zhuǎn)語句的實(shí)現(xiàn),包括標(biāo)簽的定義、跳轉(zhuǎn)語句的使用、作用域限制、避免濫用的原因以及歷史遺留代碼中的使用情況,感興趣的可以了解一下2025-03-03

