前言#
昨天我们做了一个小demo server,先使用mock的数据来实现增和查,然后我们又接入了数据库。
坏蛋Dan:go简单入门--day5:基于Gin开发RESTful API
今天我们来简单的了解下泛型
generics#
泛型这玩意儿相信大家都不陌生,可以使类型复用。
我们以一个例子来简单的了解,我们先不用泛型来实现
初始化项目#
mkdir generics
cd generics
go mod init example/generics
echo > main.go // 注意可能变成utf-16的编码non-generics#
// SumInts adds together the values of m.
func SumInts(m map[string]int64) int64 {
var s int64
for _, v := range m {
s += v
}
return s
}
// SumFloats adds together the values of m.
func SumFloats(m map[string]float64) float64 {
var s float64
for _, v := range m {
s += v
}
return s
}两个函数的逻辑都是一样的,都是计算总数。
但是不同的点就在于一个是计算整数另一个是计算浮点数,这是因为go的强类型导致这里的参数必须定义一个确定的类型并且只能接收这个类型的参数。
显而易见的是代码的重复率几乎是100%,为了这一个类型多写了一套代码。

然后我们来实现用泛型来写的
use generics#
func main() {
// Initialize a map for the integer values
ints := map[string]int64{
"first": 34,
"second": 12,
}
// Initialize a map for the float values
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
fmt.Printf("Non-Generic Sums: %v and %v\n",
SumIntsOrFloats[string, int64](ints),
SumIntsOrFloats[string, float64](floats))
}
// SumIntsOrFloats sums the values of map m. It supports both int64 and float64
// as types for map values.
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}在函数中定义的语法是:func 函数名 [泛型A 支持的类型, 泛型B 支持的类型等, 泛型C......](参数 参数类型) 返回类型 { ...函数体 }
第一眼看有些抽象,不过还是属于可以理解的范围。
K表示key,而V自然就是value,int64 | float64表示的是支持int64和float64这两种类型。
这里有一个我们并不熟悉的东西comparable,比较性。
这里做这样的声明其实是go中如果map的value需要用于比较,也就是value作为==/!=这类操作符的操作数的时候,key也得是可比性的,所以这里K是comparable是必不可少的。
而使用的时候SumIntsOrFloats[string, int64](ints)里的[string, int64]就是取代泛型的类型,大多数时候是非必要的,可以不写,因为编译器在编译阶段会自动推断。
比如这样
SumIntsOrFloats(ints),
SumIntsOrFloats(floats)) 不过有些时候则不可以省略,比如如果你的泛型函数没有参数,那么这个时候就没办法推断了。
声明类型约束(type constraint)#
type Number interface {
int64 | float64
}上面这块代码就是在定义类型约束,Number这个接口(interface)类型只能是int64或者float64 。
然后我们可以把这个类型用在刚写的泛型函数中
// SumNumbers sums the values of map m. It supports both integers
// and floats as map values.
func SumNumbers[K comparable, V Number](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}总结#
莫得
发布于 2023-04-11 17:43・IP 属地广东
