其實interface{}就相當於某種形式的泛型,然而空介面能作的事還是有限,
Go語言在其1.18版本引入了泛型的支援。這是Go語言開發史上的一個重大進步,因為泛型在很多其他語言中已經是一個基本的功能,而Go社區也長期討論此特性。
泛型提供了一種方法,讓開發者能夠編寫更具一般性,但仍然具有型別安全性的程式碼。例如,以前要為不同的型別寫不同的函式或資料結構,但有了泛型後,你可以寫一個泛型函式或資料結構,並在使用時為其提供具體的型別。
在 Go 語言裡,任何型別只要實作一個介面中的所有方法,就可以視為符合該介面型別。
而 interface{}(空介面)沒有定義任何方法,這意味著任何型別(包括內建型別)都可以代入為空介面,
當你將一個值存放到空介面中時,其動態型別(即值的實際型別)在普通情況下是被隱藏的。
為了從interface{}中取出值,你需要知道該值的型別或至少猜測其可能的型別。
這可以通過以下兩種方法實現:
var value interface{} = 42
num, ok := value.(int)
if ok {
fmt.Println("Value is of type int:", num)
} else {
fmt.Println("Value is not of type int")
}
如果該值不是該型別,ok會是false,並且num將是int的零值(也就是0)。
var value interface{} = 42
t := reflect.TypeOf(value)
v := reflect.ValueOf(value)
fmt.Println("Type of value:", t)
fmt.Println("Value:", v.Int())
在設計Go程式時,建議盡量減少interface{}的使用,除非真的有需要。過度使用空介面可能會使程式碼失去型別的安全性和可讀性。當你需要用到多型時,定義具體的介面通常是更好的選擇。
泛型範例 :
假設我們有一個函式sum(),作int加總,一開始設計如下:
func sum(a int, b int) int {
return a + b
}
如果我們想要計算int型別之外的和。 如計算浮點或字串? 解決方法之一就是像下面這樣為不同類型定義不同的函數:
func sumFloat32(a float32, b float32) float32 {
return a + b
}
func sumString(a string, b string) string {
return a + b
}
函式的參數parameter只是類似佔位符的東西並沒有具體的值,只有我們呼叫函數傳入引數(argument) 之後才有具體的值。此時我們可以針對型別也做類似的事 :
func Add(a T, b T) T {
return a + b
}
此時T就像是個型別的佔位符號,T 被稱為 type parameter, 它不是具體的型別,在定義函數時型別並不確定。 因為 T 的型別並不確定,所以我們需要像函數的 parameter 一樣,在呼叫函數的時候再傳入具體的型別。 這樣我們就能一個函數同時支援多個不同的型別了,這裡的具體型別被稱為 type argument。
//例子一
// [T=int]中的 int 是type argument,代表函數Add()定義中的型別 T 全都被 int 取代
Add[T=int](1020, 2050)
// 傳入型別int後,Add()函數的定義可近似看成下面這樣:
func Add( a int, b int) int {
return a + b
}
// 例子2:如果是兩個字串總和的時候,就傳入string類型實參
Add[T=string]("Hello", "World")
// string傳入後,Add()函數的定義可近似視為如下
func Add( a string, b string) string {
return a + b
}
為什麼不用reflect(反射)就好,理由整理如下 :
用起來麻煩:使用介面和反射來模擬泛型的效果確實需要寫更多的代碼,這會增加代碼的複雜性。例如,每次你需要檢查和轉換一個型別,你都需要寫相應的代碼。
失去了編譯時的型別檢查:這是一個非常重要的問題。Go的一個主要優點是它的強型別系統,它可以在編譯時捕捉很多錯誤。使用介面和反射繞過了這個系統,這意味著某些錯誤只能在執行時被檢測到,這顯然不是理想的情況。
性能不太理想:反射涉及很多執行時的檢查和轉換,這會降低代碼的性能。泛型,另一方面,是在編譯時進行的,所以它通常更快。
如果經常要分別為不同的類型寫完全相同邏輯的程式碼,那麼使用泛型將是最合適的選擇。
以上就是最簡單的介紹泛型,當然泛型的介紹不只這些,之後會開一個主題來講講~。