Go泛型系列:Go1.18 类型约束那些事
发布于 2021-11-18 17:35 ,所属分类:软件编程学习资料
阅读本文大概需要 6 分钟。
大家好,我是 polarisxu。
上篇《Go泛型系列:提前掌握Go泛型的基本使用》简单讲解了泛型中的约束,但约束相关内容远不止那些,本文介绍更多约束相关内容。
请安装最新的 tip 版本,方便验证本文的内容。当然,也可以通过 https://gotipplay.golang.org/在线验证。
01 语法变更
上次提到,定义约束的语法类似这样:
typeAddableinterface{
typeint,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr,float32,float64,complex64,complex128,string
}
不过目前已经确认,语法改成如下形式:
typeAddableinterface{
int|int8|int16|int32|int64|uint|uint8|uint16|uint32|uint64|uintptr|float32|float64|complex64|complex128|string
}
对于这样的修改,大家褒贬不一。就语义来说,新的方式|
有或之意,更贴切,而且少了一个type
,更简洁。
02 额外用法
除了以上提到的优点,新的方式还还有额外的用途,也就是不用每次都定义一个接口约束。
看一个具体示例:
packagemain
import(
"fmt"
)
funcadd[Tint|float64](a,bT)T{
returna+b
}
funcmain(){
fmt.Println(add(1,2))
fmt.Println(add(1.2,2.3))
//fmt.Println(add("a","b"))
}
//Output:
//3
//3.5
最后注释的一行代码,会编译报错:string does not satisfy int|float64
。
注意 add 函数的泛型约束:T int|float64
。如果约束是逗号分隔,无法采用这种语法:
funcadd[Tint,float64](a,bT)T
以上代码显然很不友好,编译器也不好解析。
采用了|
后,不需要每次都定义接口约束,可以让代码更少。不过,这种方式建议只在少数类型约束时才适合,否则可读性太差。
除了以上用法,约束还有一种用法。
在 Go 语言中,基于某类型定义新类型,有时可能希望泛型约束是某类型的所有衍生类型。看一个具体例子:
packagemain
import(
"fmt"
)
funcadd[T~string](x,yT)T{
returnx+y
}
typeMyStringstring
funcmain(){
varxstring="ab"
varyMyString="cd"
fmt.Println(add(x,x))
fmt.Println(add(y,y))
}
//Output:
//abab
//cdcd
注意 add 函数的签名:
funcadd[T~string](x,yT)T
约束~string
表示支持 string 类型以及底层是 string 类型的类型,因此 MyString 类型值也可以传递给 add。
03 注意事项
约束形式的多样性,导致 Go 泛型语法一下子复杂起来:
//没有任何约束
funcadd[Tany](x,yT)T
//约束Addble(需要单独定义)
funcadd[TAddble](x,yT)T
//约束允许int或float64类型
funcadd[Tint|float64](x,yT)T
//约束允许底层类型是string的类型(包括string类型)
funcadd[T~string](x,yT)T
在泛型中,有些场景可能想当然可以成立,但结果可能不成立,在使用时需要注意(当然,不排除将来支持)。比如:
funcMakeChan[Tchanbool|chanint](cT){
_=make(T)//错误
_=new(T)//正确
_=len(c)//正确
}
//以下代码无法编译:
//cannotrangeoverc(variableoftypeTconstrainedby[]string|map[int]string)(Thasnostructuraltype)
funcForEach[T[]string|map[int]string](cT,ffunc(int,string)){
fori,v:=rangec{
f(i,v)
}
}
ForEach 函数的签名,你能看懂吗?泛型确实让 Go 复杂起来了,虽然语法允许,但建议大家以后写泛型代码时一定要尽量保证可读性。
Go泛型系列:提前掌握Go泛型的基本使用
我是 polarisxu,北大硕士毕业,曾在 360 等知名互联网公司工作,10多年技术研发与架构经验!2012 年接触 Go 语言并创建了 Go 语言中文网!著有《Go语言编程之旅》、开源图书《Go语言标准库》等。
坚持输出技术(包括 Go、Rust 等技术)、职场心得和创业感悟!欢迎「polarisxu」一起成长!也欢迎加我好友交流:gopherstudio
相关资源