|
|
|
|
**泛型是为了解决执行逻辑与类型无关的问题**,这类问题不关心给出的类型是什么,只需要完成对应的操作就足够。golang 中的泛型与java概念相似,但是并不完善,定义时需要规定类型范围
|
|
|
|
|
|
|
|
|
|
定义了一个相加函数,输入必须是int 或者 float32
|
|
|
|
|
```golang
|
|
|
|
|
func Sum[T int | float32](a, b T) T {
|
|
|
|
|
return a + b
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//调用有2种方式
|
|
|
|
|
// 1.类型推断
|
|
|
|
|
Sum(1, 2)
|
|
|
|
|
// 2.指定类型
|
|
|
|
|
Sum[int](1, 2)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 一、泛型结构
|
|
|
|
|
|
|
|
|
|
+ 切片
|
|
|
|
|
```golang
|
|
|
|
|
//定义
|
|
|
|
|
type GenericSlice[T int | string] []T
|
|
|
|
|
//使用
|
|
|
|
|
GenericSlice[int]{1, 2, 3}
|
|
|
|
|
```
|
|
|
|
|
+ map
|
|
|
|
|
```golang
|
|
|
|
|
//定义
|
|
|
|
|
type GenericMap[K comparable, V int | string | byte] map[K]V
|
|
|
|
|
//使用
|
|
|
|
|
gmap1 := GenericMap[int, string]{1: "hello world"}
|
|
|
|
|
gmap2 := make(GenericMap[string, byte], 0)
|
|
|
|
|
```
|
|
|
|
|
+ struct
|
|
|
|
|
```golang
|
|
|
|
|
//定义
|
|
|
|
|
type GenericStruct[T int | string] struct {
|
|
|
|
|
Name string
|
|
|
|
|
Id T
|
|
|
|
|
}
|
|
|
|
|
//使用
|
|
|
|
|
GenericStruct[int]{
|
|
|
|
|
Name: "jack",
|
|
|
|
|
Id: 1024,
|
|
|
|
|
}
|
|
|
|
|
GenericStruct[string]{
|
|
|
|
|
Name: "Mike",
|
|
|
|
|
Id: "1024",
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
+ 泛型切片形参
|
|
|
|
|
```golang
|
|
|
|
|
type Company[T int | string, S int | string] struct {
|
|
|
|
|
Name string
|
|
|
|
|
Id T
|
|
|
|
|
Stuff []S
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Company[int, []int]{
|
|
|
|
|
Name: "lili",
|
|
|
|
|
Id: 1,
|
|
|
|
|
Stuff: []int{1},
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
+ 泛型接口
|
|
|
|
|
```golang
|
|
|
|
|
type SayAble[T int | string] interface {
|
|
|
|
|
Say() T
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Person[T int | string] struct {
|
|
|
|
|
msg T
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p Person[T]) Say() T {
|
|
|
|
|
return p.msg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
//定义SayAble(接口类型),然后初始化为Person,类似java向上造型
|
|
|
|
|
var s SayAble[string]
|
|
|
|
|
s = Person[string]{"hello world"}
|
|
|
|
|
fmt.Println(s.Say())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 二、类型集
|
|
|
|
|
|
|
|
|
|
```golang
|
|
|
|
|
type SignedInt interface {
|
|
|
|
|
int8 | int16 | int | int32 | int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type UnSignedInt interface {
|
|
|
|
|
uint8 | uint16 | uint32 | uint64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//并集
|
|
|
|
|
type Integer interface {
|
|
|
|
|
SignedInt | UnSignedInt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```golang
|
|
|
|
|
type SignedInt interface {
|
|
|
|
|
int8 | int16 | int | int32 | int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Integer interface {
|
|
|
|
|
int8 | int16 | int | int32 | int64 | uint8 | uint16 | uint | uint32 | uint64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//交集
|
|
|
|
|
type Number interface {
|
|
|
|
|
SignedInt
|
|
|
|
|
Int
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 三、数据结构
|
|
|
|
|
|
|
|
|
|
+ 队列
|
|
|
|
|
```golang
|
|
|
|
|
type Queue[T any] []T
|
|
|
|
|
|
|
|
|
|
func (q *Queue[T]) Push(e T) {
|
|
|
|
|
*q = append(*q, e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queue[T]) Pop(e T) (_ T) {
|
|
|
|
|
if q.Size() > 0 {
|
|
|
|
|
res := q.Peek()
|
|
|
|
|
*q = (*q)[1:]
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queue[T]) Peek() (_ T) {
|
|
|
|
|
if q.Size() > 0 {
|
|
|
|
|
return (*q)[0]
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queue[T]) Size() int {
|
|
|
|
|
return len(*q)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
+ 堆
|
|
|
|
|
堆是一种特殊的数据结构,它可以在O(1)的时间内判断最大或最小值,所以它对元素有一个要求,那就是必须是可以排序的类型,但内置的可排序类型只有数字和字符串,并且go的泛型约束不允许存在带方法的接口,所以在堆的初始化时,需要传入一个自定义的比较器,比较器由使用者提供,比较器也必须使用泛型,如下最小堆实现(数组实现最小堆有元素下标公示)
|
|
|
|
|
```golang
|
|
|
|
|
type Comparator[T any] func(a, b T) int
|
|
|
|
|
|
|
|
|
|
type BinaryHeap[T any] struct {
|
|
|
|
|
//数组容器
|
|
|
|
|
s []T
|
|
|
|
|
//比较器
|
|
|
|
|
c Comparator[T]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|