了解泛型
- 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))
}