Go語言在1.18版本中引入了泛型(Generics),這是Go語言發展中的一個重要里程碑。泛型允許你編寫更通用和可複用的程式碼,而無需犧牲型別安全性。以下是對Go中泛型的詳細介紹,包括其語法、使用場景和示例程式碼。
1. 泛型的基本概念
泛型允許你定義可以處理多種資料型別的函式和資料結構,而無需為每種型別編寫單獨的程式碼。透過使用型別引數,你可以編寫一次程式碼,然後在不同的上下文中重用它。
2. 型別引數
型別引數是泛型的核心。你可以在函式、結構體和介面中使用型別引數。型別引數在宣告時使用方括號[]
括起來,並且可以有一個或多個型別引數。
3. 型別約束
型別約束用於限制型別引數可以接受的型別。Go提供了幾種型別約束:
any
:表示任意型別。comparable
:表示可以進行比較的型別(支援==
和!=
操作)。- 可以定義自定義型別約束:
package main
import "fmt"
// 定義一個自定義型別約束
type Number interface {
int | float64
}
// 使用自定義型別約束的泛型函式
func Add[T Number](a, b T) T {
return a + b
}
func main() {
fmt.Println(Add(1, 2)) // 輸出: 3
fmt.Println(Add(1.5, 2.3)) // 輸出: 3.8
}
在這個示例中,Number
介面定義了一個自定義型別約束,表示int
或float64
型別。
4. 泛型的使用場景
泛型在以下場景中特別有用:
- 集合操作:例如,處理不同型別的列表、集合和對映。
- 演算法實現:例如,排序、搜尋和數學運算。
- 資料結構:例如,棧、佇列和樹。
- 通用庫:例如,通用的工具函式和資料處理庫。
5. 注意事項
- 效能:泛型可能會引入一些效能開銷,特別是在編譯時和執行時的型別檢查和轉換。
- 複雜性:泛型程式碼可能會增加程式碼的複雜性,特別是在型別約束和型別引數的使用上。
6. 示例
建立一個泛型函式,該函式可以接受任何型別的map
並返回其鍵的列表。為了實現這一點,我們需要定義一個泛型型別引數來表示map
的鍵和值的型別。
package main
import (
"fmt"
)
// GetKeys 返回給定 map 的所有鍵的切片
func GetKeys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
func main() {
// 示例 1:map[string]int
map1 := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
keys1 := GetKeys(map1)
fmt.Println("Keys of map1:", keys1)
// 示例 2:map[int]string
map2 := map[int]string{
1: "one",
2: "two",
3: "three",
}
keys2 := GetKeys(map2)
fmt.Println("Keys of map2:", keys2)
// 示例 3:map[float64]bool
map3 := map[float64]bool{
1.1: true,
2.2: false,
3.3: true,
}
keys3 := GetKeys(map3)
fmt.Println("Keys of map3:", keys3)
}
說明:
- 定義泛型函式:
- 函式
GetKeys
使用兩個型別引數K
和V
,其中K
表示map
的鍵型別,V
表示map
的值型別。 K
需要實現comparable
介面,因為map
的鍵必須是可比較的。V
可以是任何型別,因此使用any
作為型別約束。
- 函式
- 獲取鍵列表:
- 函式中,建立一個切片
keys
用於儲存map
的鍵。 - 透過遍歷
map
,將每個鍵新增到keys
切片中。 - 最後返回
keys
切片。
- 函式中,建立一個切片
- 示例用法:
- 在
main
函式中,定義了三個不同型別的map
,並呼叫GetKeys
函式獲取它們的鍵列表。 - 列印每個
map
的鍵列表以驗證結果。
- 在
宣告:本作品採用署名-非商業性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0)進行許可,使用時請註明出處。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 戀水無意
騰訊雲開發者社群:孟斯特