go T 泛型

目录

1、类型约束

2、泛型函数

3、泛型结构体

4、泛型接口

5、以接口作为类型约束


        关键词:泛型、类型参数、类型约束

        Go 语言在 1.18 版本引入了泛型(Generics)特性,可以编写更通用、可复用的代码,泛型可以用于:泛型函数、泛型结构体、泛型接口。

1、类型约束

        在 Go 泛型中,类型参数需要满足一定的约束条件才能被正确使用。常见的约束有:

        comparablecomparable约束要求类型参数必须是可比较的类型,即可以使用==!=进行比较的类型,比如整数、字符串、布尔值等。

        anyany约束表示类型参数可以是任意类型,它是最宽松的一种约束条件。当定义泛型接口、结构体等时,如果希望允许任何类型作为类型参数,就可以使用any约束。

        此外,还可以自定义类型约束来满足更复杂的需求,通过定义接口并在接口中定义一组方法要求,然后让类型参数满足该接口的要求来实现自定义约束。

        常用组合:[T comparable]、[T, U comparable]、[T, U any]、[T any, U comparable]、[T MyInterface]

2、泛型函数

        在函数名后面,中括号中指定:类型参数、类型约束。

        在很多情况下,编译器可以根据实参自动推断类型参数的值,这样就不需要显式地指定类型参数。

//单类型参数
func Compare[T comparable](a, b T) bool {
    return a == b
}

//显示指定类型参数
Compare[int](5, 5)
Compare[string]("hello", "hello")

//自动推断类型参数
Compare(5, 5)
Compare("hello", "hello")



//多类型参数
func Compare[T comparable, U any](a, b T, c U) bool {
	fmt.Println("c:", c)
	return a == b
}

//显示指定类型参数
Compare[int, string](1, 2, "c")

//自动推断类型参数
Compare[int](1, 2, "c")

3、泛型结构体

        定义包含类型参数的结构体,以便在结构体内部使用不同类型的数据。

        在结构体名后面,中括号中指定:类型参数、类型约束。

        在内部成员中,使用类型参数。

// 泛型结构体
type Pair[T, U any] struct {
	First  T //泛型T成员变量
	Second U //泛型U成员变量
}

// 泛型成员函数
func (p *Pair[T, U]) print(a T, b U) {
	fmt.Println(p.First)
	fmt.Println(p.Second)
	fmt.Println(a)
	fmt.Println(b)
}

func main() {
	p := Pair[string, int]{
		First:  "a",
		Second: 1,
	}

	p.print("b", 2)
}

4、泛型接口

        泛型接口可以定义一组方法,这些方法可以使用类型参数来处理不同类型的数据。

        在接口名后面,中括号中指定:类型参数、类型约束。

        在内部成员方法中,使用类型参数。

type PairInterface[T, U any] interface {
	Print(T, U)
}

// 泛型结构体
type Pair[T, U any] struct {
	First  T //泛型T成员变量
	Second U //泛型U成员变量
}

// 泛型成员函数
func (p *Pair[T, U]) Print(a T, b U) {
	fmt.Println(p.First)
	fmt.Println(p.Second)
	fmt.Println(a)
	fmt.Println(b)
}

func main() {
	p := Pair[string, int]{
		First:  "a",
		Second: 1,
	}

	p.Print("b", 2)
}

5、以接口作为类型约束

        以接口作为【类型约束】,可以在接口中定义一组方法,只有实现了接口的结构体类型才可以作为【类型参数】。

        如下,泛型函数 DoMath 的类型参数 T 的约束类型为接口 Mathable,Interger 实现了接口 Mathable,因此可以作为泛型函数 DoMath 的类型参数。

package main

import "fmt"

// Mathable接口定义了Add和Subtract两个方法要求,作为自定义类型约束
type Mathable interface {
    Add(other Mathable) Mathable
    Subtract(other Mathable) Mathable
}

// DoMath函数,T是类型参数且必须满足Mathable约束
func DoMath[T Mathable](a, b T) T {
    return a.Add(b).Subtract(b)
}

// Integer结构体实现了Mathable接口
type Integer struct {
    value int
}

func (i *Integer) Add(other *Integer) *Integer {
    return &Integer{value: i.value + other.value}
}

func (i *Integer) Subtract(other *Integer) *Integer {
    return &Integer{value: i.value - other.value}
}

func main() {
    a := Integer{value: 5}
    b := Integer{value: 3}
    result := DoMath(&a, &b)
    fmt.Println(result.value)
}

### Golang的概述 Go 语言自版本 1.18 开始支持编程特性,这使得开发者能够编写更加通用和可重用的代码。然而,在某些场景下,使用并不会显著提升代码质量反而可能增加复杂度[^1]。 ### 的基本概念 允许定义带有类型参数的函数或数据结构,这些类型参数可以在实例化时由具体的类型替代。通过这种方式,可以创建适用于多种类型的算法而不必为每种类型单独实现逻辑[^4]。 ### 创建结构体 下面是一个简单的例子展示了如何声明并初始化一个具有三个不同基础类型约束(`string`, `int`, 或 `float64`)的结构体: ```go type Struct1[T string | int | float64] struct { Title string Content T } func main() { s := Struct1[string]{Title: "Example", Content: "Hello"} } ``` 此段代码定义了一个名为 `Struct1` 的结构体,并指定了其成员字段之一 (`Content`) 可以为字符串、整数或浮点数值。在主程序中,则创建了该结构体的一个实例并将具体内容设置为了字符串类型的数据[^3]。 ### 编写函数 当涉及到操作多个相同类型的元素集合时,比如求两个数字之和的操作也可以利用来增强灵活性: ```go // Sum 计算任意两种兼容加法运算符的数值相加之总和. func Sum[T int | int32 | float32](a, b T) T { return a + b } func main(){ result := Sum[int](5,7) fmt.Println(result)// 输出:12 } ``` 上述示例中的 `Sum` 函数接受两个同类型的输入参数并通过指定类型列表 `[T int | int32 | float32]` 来限定允许传入的具体类型范围;这样做的好处在于既保持了良好的性能又提高了代码复用率。 ### 应用建议 尽管提供了强大的功能,但在实际开发过程中应当权衡利弊合理运用。对于那些已经存在良好解决方案的地方不必强行引入额外层次的抽象以免造成不必要的麻烦。只有当我们确实遇到重复模式并且确认可以通过简化设计的时候才应考虑采用它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值