泛型又叫类型参数化,指在函数、方法、接口以及类定义的时不局限指定某一种特定类型,而是其调用者来决定具体使用哪种类型的参数;
如没有泛型,当针对不同类型的相同逻辑处理会增加大量重复代码:
func AddInt(res ...int) (ans int) { for _, v := range res { ans += v } return}func AddFloat64(res ...float64) (ans float64) { for _, v := range res { ans += v } return}
泛型版本发布前, 用空接口interface{} 实现泛型函数:
func Add(res ...interface{}) (ans interface{}) { ans = res[0] for i := 1; i < len(res); i++ { switch x := res[i].(type) { case int: ans = ans.(int) + x case string: ans = ans.(string) + x case float64: ans = ans.(float64) + x } } return}
1.18版本泛型发布:
1.新增关键字:any、comparable,很明显any就是空接口;
// any is an alias for interface{} and is equivalent to interface{} in all ways.type any = interface{}// comparable is an interface that is implemented by all comparable types// (booleans, numbers, strings, pointers, channels, arrays of comparable types,// structs whose fields are all comparable types).// The comparable interface may only be used as a type parameter constraint,// not as the type of a variable.type comparable interface{ comparable }
2.新增泛型约束的概念;
//===两种表现形式===//定义约束接口type Integer interface { int | int8 | int16 | int32 | int64}func PrintInteger[T Integer](a T) { fmt.Println(a)}//直接行内多个类型组合func PrintInteger[T int | int8 | int16 | int32 | int64](a T) { fmt.Println(a)}//===================type MyInt interface { ~int //~表示该约束对任何以int为底层类型的类型有效}
所以之前多值累加函数可改为:
func Add[T ~int | ~float64 | ~string](res ...T) (ans T) { for _, v := range res { ans += v } return}
但go中泛型使用存在一些限制:
限制一:泛型约束必须是一个接口,不能是结构体;
解决方案:通过实现指定接口,将接口约束转移到结构体上;
type Entity interface { Id() int64 SetId(id int64)}type BaseEntity struct { id int64}func (b *BaseEntity) Id() int64 { return b.id}func (b *BaseEntity) SetId(id int64) { b.id = id}type EntityA struct { BaseEntity}type EntityB struct { BaseEntity}func Selector[E Entity](a E) { fmt.Println(a)}func main() { Selector(new(EntityA)) Selector(new(EntityB))}
限制二:接口和结构体无法使用泛型方法;
解决方案:结构体泛型化
type Entity[T any] struct {}func (e *Entity[T]) Exec(res ...T) {}func main() { a := &Entity[int]{} a.Exec(1, 2) b := &Entity[string]{} b.Exec("a", "b")}
限制三:泛型约束不能用于参数,只能和泛型结合一起使用;
解决方案:标记接口
type MyEntity interface { mark()}type EntityA struct {}type EntityB struct {}func (e EntityA) mark() {}func (e EntityB) mark() {}type Conn struct {}func (c *Conn) Exec(res ...MyEntity) {}
留言与评论(共有 0 条评论) “” |