8.golang泛型

代码复用,也叫模板

函数和类型(含接口)支持类型参数,方法不支持

通常以单个大写字母命名类型参数(类型参数也是go1.18才引入的,给Go带来了泛型编程的能力,之前需要使用interface编写重复的代码)

类型参数必须有约束,可以定义一个只接受实现了某个接口的类型参数的泛型函数

type Addable[T any] interface {
    Add(T) T
}
​
func Sum[T Addable[T]](a, b T) T {
    return a.Add(b)
}
​

Sum 函数的类型参数 T 被约束为必须实现了 Addable 接口

雨痕大佬的代码

package main
​
import (
    "cmp"
)
​
func maxValue[T cmp.Ordered](x, y T) T {
    if x > y { return x }
    return y
}
​
func main() {
    println(maxValue[int](1, 2))    // 实例化,类型实参。
    println(maxValue(1.1, 1.2))     // 类型推导,省略。
    //泛型可以进行类型推导,省略实例化
}
type N struct{}
func (N) String() string { return "N" }
​
func test[T fmt.Stringer](v T) {
    fmt.Println(v)
}
​
func main() {
    // test(1)
    //     int does not implement fmt.Stringer (missing method String)
​
    test(N{})
}

类型集合

接口:普通接口(能做什么)

类型约束(谁来做)(指定实现接口的类型集合

type Integer interface {
    Signed | Unsigned
}
​
type Signed interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64
}

|:匹配任一类型即可

~:底层类型(underlying type)是该类型的所有类型(断言进行判断)

泛型的实现

通常为

模板:每次调用生成代码实例,(参数类型相同

package main
​
import (
    "os"
    "text/template"
)
​
type Person struct {
    Name string
    Age  int
}
​
func main() {
    t := template.Must(template.New("person").Parse("Name: {{.Name}}, Age: {{.Age}}\n"))
    p := Person{Name: "John", Age: 30}
    t.Execute(os.Stdout, p)
}

字典:

package main
​
import "fmt"
​
func main() {
    m := make(map[string]int)
    m["Alice"] = 23
    m["Bob"] = 34
​
    fmt.Println("Map:", m)
}

golang的实现介于两者之间,GCShape stenciling with Dictionaries,使用字典进行 GCShape 模板制作

任意指针类型,或具有相同底层类型,属于同一GCShape组

8.2性能

指针版本会逃逸到堆上

type Tester interface {
    *A | *B
    test()
}
​
func test[T Tester](a T) {
    a.test()
}
​
// -----------------------------
​
func main() {
    var a A = 1
    var b B = 2
​
    test(&a)
    test(&b)
}
  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值