# 云原生系列Go语言篇-泛型Part 2

## 类型推导和泛型

type Integer interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
}
func Convert[T1, T2 Integer](in T1) T2 {
return T2(in)
}
func main() {
var a int = 10
b := Convert[int, int64](a) // 无法推导返回类型
fmt.Println(b)
}

## 类型元素限定常量

// INVALID!
func PlusOneThousand[T Integer](in T) T {
return in + 1_000
}

// VALID
func PlusOneHundred[T Integer](in T) T {
return in + 100
}

## 组合泛型函数和泛型数据结构

type OrderableFunc [T any] func(t1, t2 T) int

type Tree[T any] struct {
f    OrderableFunc[T]
root *Node[T]
}
type Node[T any] struct {
val         T
left, right *Node[T]
}

func NewTree[T any](f OrderableFunc[T]) *Tree[T] {
return &Tree[T]{
f: f,
}
}

Tree的方法非常简单，因为它调用Node来完成任务：

func (t *Tree[T]) Add(v T) {
}
func (t *Tree[T]) Contains(v T) bool {
return t.root.Contains(t.f, v)
}

func (n *Node[T]) Add(f OrderableFunc[T], v T) *Node[T] {
if n == nil {
return &Node[T]{val: v}
}
switch r := f(v, n.val); {
case r <= -1:
case r >= 1:
}
return n
}
func (n *Node[T]) Contains(f OrderableFunc[T], v T) bool {
if n == nil {
return false
}
switch r := f(v, n.val); {
case r <= -1:
return n.left.Contains(f, v)
case r >= 1:
return n.right.Contains(f, v)
}
return true
}

t1 := NewTree(cmp.Compare[int])
fmt.Println(t1.Contains(15))
fmt.Println(t1.Contains(40))

type Person struct {
Name string
Age int
}
func OrderPeople(p1, p2 Person) int {
out := cmp.Compare(p1.Name, p2.Name)
if out == 0 {
out = cmp.Compare(p1.Age, p2.Age)
}
return out
}

t2 := NewTree(OrderPeople)
fmt.Println(t2.Contains(Person{"Bob", 30}))
fmt.Println(t2.Contains(Person{"Fred", 25}))

func (p Person) Order(other Person) int {
out := cmp.Compare(p.Name, other.Name)
if out == 0 {
out = cmp.Compare(p.Age, other.Age)
}
return out
}

t3 := NewTree(Person.Order)
fmt.Println(t3.Contains(Person{"Bob", 30}))
fmt.Println(t3.Contains(Person{"Fred", 25}))

## 再谈可比较类型

type Thinger interface {
Thing()
}
type ThingerInt int
func (t ThingerInt) Thing() {
fmt.Println("ThingInt:", t)
}
type ThingerSlice []int
func (t ThingerSlice) Thing() {
fmt.Println("ThingSlice:", t)
}

func Comparer[T comparable](t1, t2 T) {
if t1 == t2 {
fmt.Println("equal!")
}
}

var a int = 10
var b int = 10
Comparer(a, b) // prints true
var a2 ThingerInt = 20
var b2 ThingerInt = 20
Comparer(a2, b2) // prints true

var a3 ThingerSlice = []int{1, 2, 3}
var b3 ThingerSlice = []int{1, 2, 3}
Comparer(a3, b3) // compile fails: "ThingerSlice does not satisfy comparable"

var a4 Thinger = a2
var b4 Thinger = b2
Comparer(a4, b4) // prints true

a4 = a3
b4 = b3
Comparer(a4, b4) // compiles, panics at runtime

## 未实现的功能

Go仍是一种小型且聚焦的编程语言，Go对泛型的实现并未包含部分在其它语言泛型中存在的特性。下面是一些Go泛型尚未实现的特性。

type functionalSlice[T any] []T
// THIS DOES NOT WORK
func (fs functionalSlice[T]) Map[E any](f func(T) E) functionalSlice[E] {
out := make(functionalSlice[E], len(fs))
for i, v := range fs {
out[i] = f(v)
}
return out
}
// THIS DOES NOT WORK
func (fs functionalSlice[T]) Reduce[E any](start E, f func(E, T) E) E {
out := start
for _, v := range fs {
out = f(out, v)
}
return out
}

var numStrings = functionalSlice[string]{"1", "2", "3"}
sum := numStrings.Map(func(s string) int {
v, _ := strconv.Atoi(s)
return v
}).Reduce(0, func(acc int, cur int) int {
return acc + cur
})

Go泛型未实现的其它特性就更加晦涩些了。有：

## 地道的Go和泛型

type Ager interface {
age() int
}
func doubleAge(a Ager) int {
return a.age() * 2
}

func doubleAgeGeneric[T Ager](a T) int {
return a.age() * 2
}

## 向标准库添加泛型

Go 1.18刚发布泛型时是很保守的。在全局添加了anycomparable接口，但并未在标准库中做出支持泛型的API调整。只做出了样式变化，将大部分标准库中的interface{}改成了any

## 小结

|
9天前
|
Go
go语言中的数据类型
go语言中的数据类型
11 0
|
15天前
|
Go 开发者

21 0
|
15天前
|

26 0
|
15天前
|

33 0
|
15天前
|
Go

19 2
|
27天前
|

Go语言小细节
Go语言小细节
36 0
|
1月前
|

Go语言中如何判断map中是否包含某个key？
【2月更文挑战第24天】
46 2
|
1月前
|

Go语言中的int和int32：同一个概念吗？
【2月更文挑战第24天】
54 3
|
15天前
|

20 0
|
9天前
|

go语言基础语法
go语言基础语法
28 1