瞭解泛型
- 1.18後引入泛型(型別引數)
- 使用者傳入引數型別
- 場景使用很少
- 1.18以前使用 [反射] 來處理不同引數型別的問題
- 泛型也是使用 [] 和陣列很像! 即:[T any]泛型的約束
- 泛型的作用:減少程式碼重複型,只針對不同型別相同功能的程式碼
- 泛型的型別:多個型別(型別不確定)
- 把靜態語言 轉換成 動態語言
泛型的型別
- T 就是一個佔位符。 型別的形式引數,T是不確定的,需要在使用時傳遞型別
- 由於T的型別是不確定的,需要增加一下約束 int|float32|float64|string
package main
import "fmt"
type s1 []int
// Slice 定義泛型切片型別, 型別引數化
/*
- T 就是一個佔位符。 型別的形式引數,T是不確定的,需要在使用時傳遞型別
- 由於T的型別是不確定的,需要增加一下約束 int|float32|float64|string
*/
type Slice[T int | float64] []T
func main() {
/* 泛型的型別 */
var a s1 = []int{1, 2, 3}
fmt.Println(a)
// 使用泛型建立變數。 泛型就是將資料語言有靜態變為動態型別
var b Slice[int] = []int{1, 2, 3}
fmt.Printf("%T\n", b) // main.Slice[int]
var c Slice[float64] = []float64{1.1, 2.2, 3.3}
fmt.Printf("%T\n", c) // main.Slice[float64]
fmt.Println("泛型:", b, c)
}
泛型使用
- 泛型的引數型別的屬性。不止一個,所有東西都可以泛型化
package main
import "fmt"
type MyStruct[T int | string] struct {
id T // 多型別
Name string
sex bool
}
type MyInterface[T string | int | float64] interface {
Print1(data string)
Print2(data T)
}
type MyChan[T string | int] chan T
func main() {
/* T 泛型的引數型別的屬性。不止一個,所有東西都可以泛型化 */
// 1. 泛型化 map GenericsMap[T,T]
type GenericsMap[K string | int | float64, V string | int | float64] map[K]V
// 1.1 例項化泛型 map
var score1 GenericsMap[string, int] = map[string]int{
"a": 100,
"b": 200,
"c": 300,
}
fmt.Printf("score1=%v\n", score1)
var score2 GenericsMap[int, int] = map[int]int{
1: 100,
2: 200,
3: 300,
}
fmt.Printf("score2=%v\n", score2)
// 2. 泛型化 slice genericsSlice[T]
type genericsSlice[T string | int | float64 | float32] []T
// 3. 結構體 泛型 MyStruct
var genericsStruct1 MyStruct[int] = MyStruct[int]{10, "張三", true}
fmt.Printf("genericsStruct1=%v\n", genericsStruct1)
var genericsStruct2 MyStruct[string] = MyStruct[string]{"我不是", "張三", true}
fmt.Printf("genericsStruct2=%v\n", genericsStruct2)
// 4. 介面泛型
//MyInterface()
// 5. 通道
//MyChan
}
特殊的泛型
package main
import "fmt"
func main() {
/* 特殊的泛型:一般不會使用*/
type MyGenericsInt[T string | int] = int // 結果一定是整型
var a1 MyGenericsInt[string] = 1
var b1 MyGenericsInt[int] = 2
fmt.Println(a1, b1)
//var c1 MyGenericsInt[string] = "1234" // 因為底層型別設定的是 int。 傳入泛型的型別任意,但是結果必須是int,即:賦值時結果是整型
}
泛型函式
package main
import "fmt"
// MySumSlice 定義泛型型別
type MySumSlice[T string | int | float64 | float32] []T
// MySumSlice 函式呼叫者泛型化
func (s MySumSlice[T]) sum(s1 int) T {
fmt.Printf("Sum s1: %d\n", s1)
var sum T
for _, v := range s {
sum += v
}
return sum
}
// Add 引數泛型化
func Add[T string | int | float64 | float32](a T, b T) T {
return a + b
}
func main() {
/*
泛型函式
- 1 呼叫者不同,傳入泛型型別。
- 2.普通函式,即:引數泛型化
*/
// 1. 呼叫者不同。 引入泛型化的資料型別呼叫函式
var intSlice MySumSlice[int] = []int{1, 2, 3, 4, 5}
intRes := intSlice.sum(1235456)
fmt.Println("intRes:", intRes)
var float32Slice MySumSlice[float32] = []float32{1.2, 2.2, 3, 4, 5}
float32Res := float32Slice.sum(222)
fmt.Println("float32Res:", float32Res)
// 2. 函式引數泛型化,同型別引數支援自動推到 ADD(int,int)
var ia int = 1
var ib int = 1
addRes1 := Add[int](ia, ib)
fmt.Println("addRes1:", addRes1)
var fa float32 = 12.33
var fb float32 = 1.235 // 遵循四捨五入
addRes2 := Add[float32](fa, fb)
fmt.Println("addRes2:", addRes2)
var sa string = "abc"
var sb string = "xyz"
addRes3 := Add[string](sa, sb)
fmt.Println("addRes3:", addRes3)
}
自定義泛型
package main
import "fmt"
type genericsInterface interface {
string | int | float64 | float32 | int8 | int16 | int32
}
func getMax[T genericsInterface](a, b T) T {
if a > b {
return a
}
return b
}
func main() {
/* 自定義泛型 */
var a = 10
var b = 20
fmt.Println(getMax(a, b))
var c = "10"
var d = "20"
fmt.Println(getMax(c, d))
}
內建泛型
package main
import "fmt"
// int8 衍生型別
type int8AT int8 // int8AT 就是 int8 的衍生型別
type int8BT int8 // intB 就是 int8 的衍生型別
// MyGenerics01 自定義 泛型型別 介面. ~表示可以匹配該型別的衍生型別
type MyGenerics01 interface {
~int8
}
func compareTheSize[T MyGenerics01](a, b T) T {
if a > b {
return a
}
return b
}
func main() {
/*
內建泛型
- any 就是一個泛型,內建型別。interface{}
- comparable 表示比較所有的型別
- 新符號 (~)衍生型別
*/
// ~ 新符號使用
var a1 int8AT = 3
var b1 int8AT = 5
fmt.Println(a1, b1)
fmt.Printf("%T\n", a1) // main.int8AT
fmt.Printf("%T\n", b1) // main.int8BT
//fmt.Println(compareTheSize(a1, b1))
fmt.Println(compareTheSize(b1, a1))
}