go -泛型

什么是泛型

泛型即开发过程中编写适用于所有类型的模板,只有在具体使用的时候才能确定真正的类型

泛型的作用与应用场景

  1. 增加代码的复用,从同类型的复用到不同类型的代码复用
  2. 应用于不同类型间代码复用的场景,即不同类型需要写相同的处理逻辑时,最适合用泛型

泛型的利弊

  1. 提高了代码复用率,提高了编程效率
  2. 不同类型间代码复用,使代码风格更加优雅
  3. 增加了编译器的负担,降低了编译效率

golang泛型的使用

泛型函数

泛型函数的快速入门

func getMaxNum[T int | float32 | float32](a, b T) T {
	if a > b {
		return a
	}
	return b
}

使用接口定义泛型约束

func getMaxNum[T CusNumT](a, b T) T {
	if a > b {
		return a
	}
	return b
}

type CusNumT interface {	//定义泛型类型约束
	//支持uint8 | float32 | float64 | ~int64及其衍生类型
	//~ 表示支持类型的衍生类型
	//  多行之间取并集
	uint8 | float32 | float64 | ~int64
	int32 | float64 | ~int64 | uint16
}

// MyInt64 为int64的衍生类型,是具有基础类型int64的新类型, 与int64不同类型
type MyInt64 int64

内置类型
any代表任意类型,comparable 类型, 只支持 == != 两个操作

// BuiltInCase 内置类型
func BuiltInCase() {
	var a, b string = "abc", "123"
	fmt.Println("内置 comparable 泛型类型约束", getBuiltInComparable(a, b))
	var c, d float64 = 100, 100
	fmt.Println("内置 comparable 泛型类型约束", getBuiltInComparable(c, d))
}

func getBuiltInComparable[T comparable](a, b T) bool {
	//comparable 类型, 只支持 == != 两个操作
	if a == b {
		return true
	}

	return false
}

泛型类型

package _case

import (
	"fmt"
)

type user struct {
	ID   int64
	Name string
	Age  uint8
}

type address struct {
	ID       int
	Province string
	City     string
}

// 集合转列表
func mapToList[k comparable, T any](mp map[k]T) []T {
	list := make([]T, len(mp))
	var i int
	for _, data := range mp {
		list[i] = data
		i++
	}
	return list
}

func myPrintln[T any](ch chan T) { //h是一个通道(channel),其元素类型为T
	for data := range ch {
		fmt.Println(data)
	}
}

// 泛型切片的定义
type List[T any] []T

// 泛型集合的定义
type MapT[k comparable, v any] map[k]v

// 泛型通道的定义
type Chan[T any] chan T

func TTypeCase() {
	userMp := make(MapT[int64, user], 0)
	userMp[1] = user{
		ID:   1,
		Name: "jack",
		Age:  18,
	}
	userMp[2] = user{
		ID:   2,
		Name: "Tom",
		Age:  19,
	}

	var userList List[user]
	userList = mapToList[int64, user](userMp)

	ch := make(Chan[user])
	go myPrintln(ch)
	for _, u := range userList {
		ch <- u
	}

	addrMp := make(MapT[int64, address], 0)
	addrMp[1] = address{
		ID:       1,
		Province: "四川",
		City:     "中国",
	}
	addrMp[2] = address{
		ID:       2,
		Province: "新疆",
		City:     "中国",
	}
	var addrList []address
	addrList = mapToList[int64, address](addrMp)

	ch1 := make(Chan[address])
	go myPrintln(ch1)
	for _, a := range addrList {
		ch1 <- a
	}
}

泛型接口

GetKey实现了any接口即 实现interface{}空接口,可以被任意类型调用
Get为其实现的接口

// 泛型接口
type GetKey[T comparable] interface {
	any     //即为 interface{}	继承了空接口的特性
	Get() T //传入的泛型为 comparable
}

其中T GetKey可以被看作实现了GetKey中Get接口的类型,所以实现了Get()接口,另一个接口又为空接口 就可以使用GetKey

// 列表转集合
func listToMap[k comparable, T GetKey[k]](list []T) map[k]T { //T 可以被看作实现GetKey中Get()接口的类型
	mp := make(MapT[k, T], len(list))
	for _, data := range list {
		mp[data.Get()] = data //data.Get 是传入的对象调用其实现的Get方法
	}
	return mp
}
func (u user) Get() int64 { //user 实现Get方法
	return u.ID
}
func (addr address) Get() int { //address 实现Get方法
	return addr.ID
}

完整代码

package _case

import "fmt"

// 基本接口,可用于变量的定义
type ToString interface {
	String() string
}

func (u user) String() string {
	return fmt.Sprintf("ID: %d, Name: %s, Age: %d", u.ID, u.Name, u.Age)
}
func (addr address) String() string {
	return fmt.Sprintf("ID: %d, Province: %s, City: %s", addr.ID, addr.Province, addr.City)
}

// 泛型接口
type GetKey[T comparable] interface {
	any     //即为 interface{}	继承了空接口的特性
	Get() T //传入的泛型为 comparable
}

func (u user) Get() int64 { //user 实现Get方法
	return u.ID
}
func (addr address) Get() int { //address 实现Get方法
	return addr.ID
}

// 列表转集合
func listToMap[k comparable, T GetKey[k]](list []T) map[k]T { //T 可以被看作实现GetKey中Get()接口的类型
	mp := make(MapT[k, T], len(list))
	for _, data := range list {
		mp[data.Get()] = data //data.Get 是传入的对象调用其实现的Get方法
	}
	return mp
}

func InterfaceCase() {
	userList := []GetKey[int64]{ //存储实现了 Get() 方法且返回类型为 int64 的类型的集合
		user{ID: 1, Name: "jack", Age: 18},
		user{ID: 2, Name: "Tom", Age: 19},
	}

	addrList := []GetKey[int]{
		address{ID: 1, Province: "四川", City: "中国"},
		address{ID: 2, Province: "新疆", City: "中国"},
	}

	userMp := listToMap[int64, GetKey[int64]](userList) //将实现GetKey接口返回值为int64的数据类型转为集合
	addrMp := listToMap[int, GetKey[int]](addrList)

	fmt.Println(userMp)
	fmt.Println(addrMp)
}

泛型结构体

注意事项:在泛型中使用指针定义会被当做表达式,需要使用interface来定义指针

// MyStruct 泛型结构体
type MyStruct[T interface{ *int | *string }] struct { //在结构体中泛型使用指针定义会被看成常量表达式,使用interface
	Name string
	Data T
}

泛型receiver

// GetData 泛型receiver
func (myStruct MyStruct[T]) GetData() T {
	return myStruct.Data
}

泛型限制

  1. 匿名结构体与匿名函数不支持泛型
  2. 不支持类型断言
  3. 不支持泛型方法,只能通过receiver来实现方法的泛型处理
  4. ~后的类型必须为基本类型,不能为接口类型
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值