泛型
go1.18版本开始支持 在函数上使用[T 支持的类型] 表示泛型,比如
func AddSum[T int|float64](params ...T)(sum T){
return sum
}
自带泛型:
- any 表示任何类型,即interface
- comparable 表示可以被比较的类型
comparable is an interface that is implemented by all comparable types (booleans, numbers, strings, pointers, channels, arrays of comparable types, structs whose fields are all comparable types). The comparable interface may only be used as a type parameter constraint, not as the type of a variable.
就个人而言,泛型的使用倒是可以解决不同类型的相同函数的编写,但是对于其其它妙用还不太明确,需要慢慢体会
在函数上申明多个类型约束
func AddElem[T int | string](params []T) (sum T) {
for _, elem := range params {
sum += elem
}
return
}
func TestGenerics_AddElem(t *testing.T) {
intSum := AddElem([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
t.Logf("测试1.1: 类型=%T,val=%+v", intSum, intSum)
strSum := AddElem([]string{"静", "以", "修", "身", ",", "俭", "以", "养", "德"})
t.Logf("测试1.2: 类型=%T,val=%+v", strSum, strSum)
}
声明一个约束集合
type NumStr interface {
~int | ~uint | ~float64 | ~string
}
type MyInt int
func AddNumStr[T NumStr](params []T) (sum T) {
for _, param := range params {
sum += param
}
return
}
func TestGenerics_AddNumStr(t *testing.T) {
intSum := AddNumStr([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
t.Logf("测试2.1: 类型=%T,val=%+v", intSum, intSum)
strSum := AddNumStr([]string{"风", "平", "浪", "静"})
t.Logf("测试2.2: 类型=%T,val=%+v", strSum, strSum)
myIntSum := AddNumStr([]MyInt{1, 2, 3, 4, 5, 6, 7, 8, 9})
t.Logf("测试2.3: 类型=%T,val=%+v", myIntSum, myIntSum)
}
泛型切片
type Vector[T any] []T
type NumSlice[T int | float64] []T
func AddElem[T int | string](params []T) (sum T) {
for _, elem := range params {
sum += elem
}
return
}
func TestGenerics_Slice(t *testing.T) {
v := Vector[string]{"z", "x", "c"}
t.Logf("测试3.1: 类型=%T,val=%+v", v, v)
ns := NumSlice[int]{1, 2, 3, 4, 5, 6}
t.Logf("测试3.2: 类型=%T,val=%+v", ns, ns)
sum := AddElem(ns)
t.Logf("测试3.3: 类型=%T,val=%+v", sum, sum)
}
泛型Map
type M[K string, V any] map[K]V
func TestGenerics_Map(t *testing.T) {
m := M[string, int]{
"zx": 123,
"as": 456,
"qw": 789,
}
t.Logf("测试4.1: 类型=%T,val=%+v", m, m)
}
泛型通道
type Ch[T any] chan T
func TestGenerics_Chan(t *testing.T) {
ch := make(Ch[int], 1)
ch <- 10
res := <-ch
t.Logf("测试5.1: 类型=%T,val=%+v", res, res)
t.Logf("测试5.2: 类型=%T,val=%+v", ch, ch)
}
方法约束
type FlyAnimal interface {
ToString() string
}
type Dragon int
func (d Dragon) ToString() string {
return "string_" + strconv.Itoa(int(d))
}
type Tiger int
func PrintStr[T FlyAnimal](params ...T) {
for _, param := range params {
fmt.Println(param.ToString())
}
}
func TestGenerics_Method_limit(t *testing.T) {
dragon := Dragon(1)
PrintStr(dragon)
}
类型加方法的双重约束
type CanSpeak interface {
~int | ~int32 | ~int64 | ~float32 | ~float64
Speak() string
}
type Mouth int32
func (m Mouth) Speak() string {
return fmt.Sprintf("speak %v", m)
}
type Nose string
func (n Nose) Speak() string {
return fmt.Sprintf("speak %v", n)
}
type Ear int
func SpeakLoudly[T CanSpeak](params []T) {
for _, param := range params {
fmt.Println(param.Speak())
}
}
func TestGenerics_Type_Method_Limit(t *testing.T) {
SpeakLoudly([]Mouth{1, 2, 3, 4, 5, 6})
}
参考
golang泛型介绍
|