从1.18版本开始,Go添加了对泛型的支持,即类型参数
泛型函数
没有泛型的痛点
- 对于相近类型的操作,可能会写多个一模一样的函数
- 不停的类型转换
package main
import "fmt"
// 遍历int切片
func PrintIntSlice(slice []int) {
for _, v := range slice {
fmt.Printf("%T %v\n", v, v)
}
}
// 遍历int64切片
func PrintInt64Slice(slice []int64) {
for _, v := range slice {
fmt.Printf("%T %v\n", v, v)
}
}
// int64切片转int切片
func Int64SliceToIntSlice(Int64Slice []int64) (IntSlice []int) {
for _, v := range Int64Slice {
IntSlice = append(IntSlice, int(v))
}
return
}
func main() {
PrintIntSlice([]int{1, 2, 3, 4, 5})
var int64Slice []int64 = []int64{4, 5, 7}
PrintInt64Slice(int64Slice)
var intSlice []int
for _, v := range int64Slice {
intSlice = append(intSlice, int(v))
}
PrintIntSlice(intSlice)
PrintIntSlice(Int64SliceToIntSlice(int64Slice))
}
有了泛型函数,就很方便
package main
import "fmt"
// 泛型函数
func PrintSliceTypeSlice[T int | int64 | string](slice []T) {
fmt.Printf("%T\n", slice)
for _, v := range slice {
fmt.Printf("%T %v\n", v, v)
}
}
func main() {
PrintSliceTypeSlice([]int{1, 2, 3, 4, 5})
PrintSliceTypeSlice([]int64{1, 2, 3, 4, 5})
PrintSliceTypeSlice([]string{"hello"})
// 标准写法
PrintSliceTypeSlice[int]([]int{1, 2, 3, 4, 5})
PrintSliceTypeSlice[int64]([]int64{1, 2, 3, 4, 5})
PrintSliceTypeSlice[string]([]string{"hello"})
}
泛型切片
package main
import "fmt"
type mySlice[T int | string] []T
func printIntTypeSlice[T int | int64 | string](slice []T) {
fmt.Printf("%T\n", slice)
for _, v := range slice {
fmt.Printf("%T %v\n", v, v)
}
}
func main() {
v1 := mySlice[int]{1, 2, 3, 4, 5}
printIntTypeSlice(v1)
v2 := mySlice[string]{"hello"}
printIntTypeSlice(v2)
}
泛型map
package main
import "fmt"
type myMap[K string | int, V any] map[K]V
type _User struct {
Name string
}
func main() {
m1 := myMap[string, string]{
"key": "fengfeng",
}
fmt.Println(m1)
m2 := myMap[int, _User]{
0: _User{"枫枫"},
}
fmt.Println(m2)
}
泛型约束
约束参数
package main
import "fmt"
type NumStr interface {
Num | Str
}
// ~的意思就是底层数据类型
type Num interface {
~int | ~int32 | ~int64 | ~uint8
}
type Str interface {
string
}
type Status uint8
type mySlice1[T NumStr] []T
func main() {
m1 := mySlice1[int]{1, 2, 3}
fmt.Println(m1)
m2 := mySlice1[int64]{1, 2, 3}
fmt.Println(m2)
m3 := mySlice1[string]{"hello"}
fmt.Println(m3)
m4 := mySlice1[Status]{1, 2, 3}
fmt.Println(m4)
}
约束方法
package main
import (
"fmt"
"strconv"
)
type Price int
func (p Price) String() string {
// int转数字
return strconv.Itoa(int(p))
}
type Price2 string
func (p Price2) String() string {
// int转数字
return string(p)
}
type showPrice interface {
~int | ~string
String() string
}
func showPriceFunc[T showPrice](p T) {
fmt.Println(p.String())
}
func main() {
var p1 Price = 12
showPriceFunc(p1)
var p2 Price2 = "56"
showPriceFunc(p2)
}