#golang 方法泛型

函数泛型是ok的。


func sumArr[T int | float64](arr []T) T {
    var sum T
    for _, val := range arr {
        //累计求和
        sum += val
    }
    return sum
}

func average[T int | float64](arr []T) float64 {
    var sum T
    for _, num := range arr {
        sum += num
    }
    avg := float64(sum) / float64(len(arr))
    return decimal(avg)
}

#目前Go的方法并不支持泛型,如下:

type A struct {
}

// 不支持泛型方法
func (receiver A) Add[T int | float32 | float64](a T, b T) T {
    return a + b
}
但是因为receiver支持泛型, 所以如果想在方法中使用泛型的话,目前唯一的办法就是曲线救国,迂回地通过receiver使用类型形参:

type A[T int | float32 | float64] struct {
}

// 方法可以使用类型定义中的形参 T 
func (receiver A[T]) Add(a T, b T) T {
    return a + b
}

// 用法:
var a A[int]
a.Add(1, 2)

var aa A[float32]
aa.Add(1.0, 2.0)

https://segmentfault.com/a/1190000041634906

#把类型约束给单独拿出来; 接口和接口、接口和普通类型之间也是可以通过 | 进行组合

太长泛型写法, 简写; 
type IntUintFloat interface {
    int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}

type Slice[T IntUintFloat] []T

type Int interface {
    int | int8 | int16 | int32 | int64
}

// 接口和接口、接口和普通类型之间也是可以通过 | 进行组合

type Uint interface {
    uint | uint8 | uint16 | uint32
}

type Float interface {
    float32 | float64
}

type Slice[T Int | Uint | Float] []T  // 使用 '|' 将多个接口类型组合


type SliceElement interface {
    Int | Uint | Float | string // 组合了三个接口类型并额外增加了一个 string 类型
}

type Slice[T SliceElement] []T 

#~指定 底层类型

var s1 Slice[int] // 正确 

type MyInt int
var s2 Slice[MyInt] // ✗ 错误。MyInt类型底层类型是int但并不是int类型,不符合 Slice[T] 的类型约束

type Int interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64
}

#并集 交集

type AllInt interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint32
}

type Uint interface {
    ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

type A interface { // 接口A代表的类型集是 AllInt 和 Uint 的交集
    AllInt
    Uint
}

type B interface { // 接口B代表的类型集是 AllInt 和 ~int 的交集
    AllInt
    ~int
}

Go1.18开始将接口分为了两种类型

  • 基本接口(Basic interface)
  • 一般接口(General interface)
type Uint interface { // 接口 Uint 中有类型,所以是一般接口
    ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

type ReadWriter interface {  // ReadWriter 接口既有方法也有类型,所以是一般接口
    ~string | ~[]rune

    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
}

//  类型BytesReadWriter 没有实现接口 Readwriter
type BytesReadWriter []byte 

func (s BytesReadWriter) Read(p []byte) (n int, err error) {
 ...
}

func (s BytesReadWriter) Write(p []byte) (n int, err error) {
 ...
}

里面太多,太杂,实际项目 谁要为了省那2函数,搞这么饶,这么复杂... 💊💊💊🔪🔪🌿🍀🍁🍂🍃 参考原文: Go 1.18 泛型全面讲解:一篇讲清泛型的全部