[Go]泛型
使用方法
下面展示一下 go 泛型的基本使用方法
package main
import "fmt"
func main() {
fmt.Printf("%v",Age[int](12))
}
func Age[T any](t T) T{
return t
}
这是函数使用泛型的写法,当函数使用泛型的时候,需要在变量前使用中括号标注泛型的具体约束,然后后面才能使用这个泛型类型,使用泛型函数的时候,中括号是可以省略的 Age(12) 系统会自动推算泛型的具体实现。顺便说一下,泛型类型使用 %v 作为占位符,也就是默认的类型,泛型类型无法进行断言。
当然了,我么也可以不用 any,自定义一个约束
package main
import "fmt"
func main() {
Age[int](12)
}
type st interface{
int | string
}
func Age[T st](t T) {
fmt.Println((t))
}
看完了在函数内的泛型,我们在看一下在方法中如何使用泛型
package main
import "fmt"
func main() {
new(Age[int]).Post(12)
var dd DD[int]
dd.TT(12)
}
type Age[T any] struct {
I T
}
func (a *Age[T]) Post(t T) {
fmt.Println(a.I, t)
}
type DD[T any] []T
func(dd *DD[T])TT(t T){
fmt.Println(t,len(*dd))
}
在 age 结构体声明的时候,声明了一个泛型 T,在 struct 体内就可以使用这个 T,方法内部仅可以使用定义在这个结构体对象上的泛型
下面是一个错误案例
// ❌
func (a *Age[T])Post[B any](t T,b B) {
fmt.Println(a.I, t)
}
syntax error: method must have no type parameters
接下来我们看一下,如何使用有类型也有方法的泛型
package main
import "fmt"
func main() {
var d DDD
var i DDD
d = 1
i = 2
io := AbsDifference[DDD](d, i)
fmt.Println(io)
}
type DDD int
func (ddd DDD) Abs() DDD {
return ddd + ddd
}
type NumericAbs[T any] interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~complex64 | ~complex128
Abs() T
}
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func AbsDifference[T NumericAbs[T]](a, b T) T {
d := a - b
return d.Abs()
}
用例子学泛型
函数泛型 map-filter-reduce
package main
import (
"fmt"
)
func main() {
vM := Map[int]([]int{1, 2, 3, 4, 5}, func(i int) int {
return i + i
})
fmt.Printf("map的结果是:%v", vM)
vF := Filter[int]([]int{1, 2, 3, 4, 5}, func(t int) bool {
if t > 2 {
return true
}
return false
})
fmt.Printf("filter的结果是:%v", vF)
vR := Reduce[Value, *Result]([]Value{
{name: "tt", year: 1},
{name: "bb", year: 2},
{name: "7i", year: 3},
{name: "8i", year: 4},
{name: "u4i", year: 5},
{name: "uei", year: 6},
{name: "uwi", year: 7},
{name: "uti", year: 8},
}, &Result{}, func(r *Result, v Value) *Result {
r.value = r.value + v.year
return r
})
fmt.Println("reduce的结果是:", vR.value)
}
// Map:类似于洗菜,进去的菜和出来的菜不一样了所以需要两种种类
func Map[T1, T2 any](arr []T1, f func(T1) T2) []T2 {
result := make([]T2, len(arr))
for k, v := range arr {
result[k] = f(v)
}
return result
}
// Filter:类似于摘菜,进去的菜和出来的菜是一种,不过量减少了
func Filter[T any](arr []T, f func(T) bool) []T {
var result []T
for _, v := range arr {
if f(v) {
result = append(result, v)
}
}
return result
}
// Reduce:类似于做菜,将菜做成一道料理,所以需要两种类型
func Reduce[T1, T2 any](arr []T1, zero T2, f func(T2, T1) T2) T2 {
result := zero
for _, v := range arr {
result = f(result, v)
}
return result
}
type Value struct {
name string
year int
}
type Result struct {
value int
}
例子二:方法上的泛型 sets
package main
import (
"fmt"
)
func main() {
// 这里 Sets的具体类型和Make的具体类型都是int,所以可以正常赋值
var s Sets[int] = Make[int]()
//
s.Add(1)
s.Add(2)
fmt.Println(s)
fmt.Println(s.Contains(3))
fmt.Println(s.Len())
s.Iterate(func(i int) {
fmt.Println(i)
})
fmt.Println(s)
s.Delete(2)
fmt.Println(s)
}
// Sets 一个key 存储对象
type Sets[T comparable] map[T]struct{}
// Make 实例化一个map
func Make[D comparable]() Sets[D] {
// 泛型就像一个管道一样,只要实例化的时候管子里的东西一致,那么就是一根管子
return make(Sets[D])
}
// Add 向这个sets添加内容
func (s Sets[T]) Add(t T) {
s[t] = struct{}{}
}
// delete ,从这个sets中删除内容
func (s Sets[T]) Delete(t T) {
delete(s, t)
}
// Contains 播报t是否属于这个sets
func (s Sets[T]) Contains(t T) bool {
_, ok := s[t]
return ok
}
//Len sets拥有的长度
func (s Sets[T]) Len() int {
return len(s)
}
// Iterate 迭代器,并且给予每个元素功能
func (s Sets[T]) Iterate(f func(T)) {
for k := range s {
f(k)
}
}
例子三:外部定义的约束 实现一个sort接口类型
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
// ~ 代表只要底层满足这些类型也可以算满足约束
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uintptr |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64 | ~string
}
type orderedSlice[T Ordered] []T
func (s orderedSlice[T]) Len() int { return len(s) }
func (s orderedSlice[T]) Less(i, j int) bool { return s[i] < s[j] }
func (s orderedSlice[T]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func OrderedSlice[T Ordered](s []T) {
sort.Sort(orderedSlice[T](s))
}