Go 1.18 在 2022 年 3 月 15 日发布,根据团队的博文介绍,1.18 版本包含 4 个重要特性:
- 泛型;
- fuzzing;
- 工作空间;
- 20% 的性能提升;
泛型
泛型是一种无须关心具体操作类型的编码方式,它将逻辑实现与具体类型解耦,体现在程序中的 3 个地方:
- 函数和类型的类型参数;
- 用于指定类型的集合;
- 类型推断,不需要显式指定类型;
本节是官方泛型教程的截取或修改内容,详细请查看此处。
不同类型求和函数
package main
import "fmt"
// sumInts 计算 int slice 的和
func sumInts(values []int) int {
var total int
for _, value := range values {
total += value
}
return total
}
// sumFloat32s 计算 float32 slice 的和
func sumFloat32s(values []float32) float32 {
var total float32
for _, value := range values {
total += value
}
return total
}
// sum 计算的 slice 元素可以是 int 类型或 float32 类型
func sum[Element int | float32](values []Element) Element {
var total Element
for _, value := range values {
total += value
}
return total
}
func main() {
intValues := []int{1, 2, 3}
float32Values := []float32{4, 5, 6}
fmt.Println(sumInts(intValues))
fmt.Println(sumFloat32s(float32Values))
// sum(intValues) 等价于 sum[int](intValues)
fmt.Println(sum(intValues))
fmt.Println(sum[int](intValues))
// sum(float32Values) 等价于 sum[float32](float32Values)
fmt.Println(sum(float32Values))
fmt.Println(sum[float32](float32Values))
}
类型约束
示例 1:
package main
import "fmt"
// Number 类型约束,限制 Number 可以是 int 或 float32
type Number interface {
int | float32
}
// sum 求和
// [Element Number] 限定 Element 需要符合 Number 类型约束
// 即 Element 只能是 int 或 float32
func sum[Element Number](values []Element) Element {
var total Element
for _, value := range values {
total += value
}
return total
}
func main() {
intValues := []int{1, 2, 3}
float32Values := []float32{4, 5, 6}
fmt.Println(sum(intValues))
fmt.Println(sum(float32Values))
}
示例 2:
package main
import "fmt"
// Flag 底层类型为 int
type Flag int
const (
Flag_A Flag = iota
Flag_B
Flag_C
)
// Number 类型约束
// ~ 操作符表示底层类型为 int 的类型也符合
type Number interface {
float32 | ~int
}
func sum[Element Number](values []Element) Element {
var total Element
for _, value := range values {
total += value
}
return total
}
func main() {
flagValues := []Flag{
Flag_A, Flag_B, Flag_C,
}
float32Values := []float32{4, 5, 6}
fmt.Println(sum(flagValues))
fmt.Println(sum(float32Values))
}
示例 3:
package main
import (
"fmt"
"strconv"
)
type Flag int
func (f Flag) String() string {
return strconv.Itoa(int(f))
}
const Flag_A Flag = iota
// Number 包含了方法的类型约束
// 指定了 Number 类型的底层类型是 int 并实现了 String() string 方法
type Number interface {
~int
String() string
}
func PrintNumber[V Number](number V) {
fmt.Println(number.String())
}
func main() {
PrintNumber(Flag_A)
}
示例 4:
package main
import "fmt"
type Flag int
const (
Flag_A Flag = iota
)
// PrintNumber 使用 ~ 操作符,定义类型底层实现
func PrintNumber[Number ~int](value Number) {
fmt.Println(value)
}
func main() {
PrintNumber(Flag_A)
PrintNumber(1)
}
总结
- 使用泛型可以减少相同逻辑(不同具体类型)的代码量;
- 使用
~
操作符指定底层类型; - 类型约束中可以声明方法;
评论