
升级Go版本到 1.18
下载地址:GO1.18
问题所在
相信有过其他语言编程基础的人,对于以下代码肯定看不下去:
以下代码来源与golang官网:https://go.dev/doc/tutorial/generics
package mainimport "fmt"func SumInts(m map[string]int64) int64 {var s int64for _, v := range m {s += v}return s}func SumFloats(m map[string]float64) float64 {var s float64for _, v := range m {s += v}return s}func main() {ints := map[string]int64{"first": 34,"second": 56,}floats := map[string]float64{"first": 35.98,"second": 43.8,}sumInts := SumInts(ints)sumFloats := SumFloats(floats)fmt.Println("结果:", sumInts, sumFloats)}
蛋疼的临时解决方案
在Go1.18之前也不是没有办法解决,可以使用接口类型实现:
func SumIntOrFloats(m map[string]interface{}) (int64, float64) {var s1 int64var s2 float64for _, v := range m {switch v.(type) {case int64:vint := v.(int64)s1 += vintcase float64:vfloat := v.(float64)s2 += vfloat}}return s1, s2}
以上代码写的也很别扭,还不如多写一个方法,反而更简单一些,你如果有其他更简单的实现方式也可以留言。
泛型终于来了--被放鸽子多次之后
直接上代码:
package mainimport "fmt"//类型参数约束type comparable interface {~string | ~int64 | ~float64}func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {var s Vfor _, v := range m {s += v}return s}func main() {ints := map[string]int64{"first": 34,"second": 56,}floats := map[string]float64{"first": 35.98,"second": 43.8,}orFloats := SumIntsOrFloats(ints)intsOrFloats := SumIntsOrFloats(floats)fmt.Println("结果:", orFloats, intsOrFloats)}
类型参数
看了以上泛型代码,没错这就是Go的泛型语法
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) Vfunc 方法名[类型参数](形式参数)返回值
简单案例
//这里类型参数限制,Max方法可以接收int64以及float64类型的参数func Max[T int64 | float64](a, b T) T {if a >= b {return a}return b}func main(){var a int64 = 1var b int64 = 2//这里调用的时候参数类型必须一致,a,b类型要么int64要么都是float64res := Max(a, b)fmt.Println(res)var c float64 = 1.1var d float64 = 2.1res1 := Max(c, d)fmt.Println(res1)}
类型参数约束
类型参数约束条件简单表示形式
1,直接写在 [] 中
Max[T int64 | float64]
2,定义约束接口 Number
type Number interface {int64 | float64}func Max[T Number](a, b T) T {if a >= b {return a}return b}
3,标准库内置的类型参数约束
any
// any is an alias for interface{} and is equivalent to interface{} in all ways.// any其实就是一个空接口,所有类型,也就是没有约束type any = interface{}func useAny[T any](t T) T {return t}
comparable
// 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 }func useComparable[T comparable](t T) T {return t}
关于内置的comparable不清楚为啥在map key的约束中不能使用,以下使用了自己定义的comparable约束,但是使用Go内置的comparable直接飘红了
//参数约束type comparable interface {~string | ~int64 | ~float64}func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V

constraints
非标准库的泛型约束,在Go1.18的beta版本中Go开发者其实有把constraints放到标准库中,后面考虑到最佳实践问题,具体需不需要constraints包中的约束就交给用户去实践,因此放在了exp包下 golang.org/x/exp/constraints
package constraintstype Signed interface {~int | ~int8 | ~int16 | ~int32 | ~int64}type Unsigned interface {~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr}type Integer interface {Signed | Unsigned}type Float interface {~float32 | ~float64}type Complex interface {~complex64 | ~complex128}type Ordered interface {Integer | Float | ~string}
关于泛型约束还有很多其他的写法,这里就不做展开,先介绍简单的使用方式,后续在慢慢深入讲解。
总结
1,本文讲解了没有泛型时写通用代码遇到的问题
2,简单泛型的使用方式
3,泛型类型参数
4,类型参数约束
5,内置的参数约束
6,非标准库的泛型参数约束
参考链接:
1,https://go.dev/doc/tutorial/generics
文章评论