前言
最近突然发现golang
更新版本1.18
了, 于是迫不及待的来看看这个版本加了些什么新特性. 没准就有之前困扰很久的问题, 在新版本被官方解决了呢.
先简单概述一下都有些什么变化, 后面再细说:
- 增加泛型的支持
- 系统库方法增加
- 修复 bug
另外, 像"系统内核更新"这种, 我们在实际开发中根本就无需关心的内容, 我就没有列出, 完整更新内容到官网去看吧. 1.18
版本的官方说明链接: https://golang.google.cn/doc/go1.18
其实, 整个看下来, 最大的变动就是增加了泛型的支持. 可以说是千呼万唤始出来了. 主要就看看这个泛型呗. 有需要的快升级了, 官方的说法是, 完全向后兼容.
泛型
还记得在这之前, 要写一个返回二者最小值的min
函数, 我们是怎么做的呢?
/*
方案一
每个类型都添加一个方法
*/
func minInt(a, b int) int {
if a < b {
return a
} else {
return b
}
}
func minInt64(a, b int64) int64 {
if a < b {
return a
} else {
return b
}
}
// ... 其他类型的方法
/*
方案二
通过 interface 接收参数并返回
*/
func min(a, b interface{}) interface{} {
changeToFloat64 := func(v interface{}) float64 {
if vInt64, ok := v.(int64); ok {
return float64(vInt64)
} else if vInt32, ok := v.(int32); ok {
return float64(vInt32)
} else if vInt, ok := v.(int); ok {
return float64(vInt)
} else if vFloat32, ok := v.(float32); ok {
return float64(vFloat32)
} else if vFloat64, ok := v.(float64); ok {
return vFloat64
} else { // 其他类型判断
return 0
}
}
floatA := changeToFloat64(a)
floatB := changeToFloat64(b)
if floatA < floatB {
return floatA
} else {
return floatB
}
}
而这两种实现方式都存在其不足.
方案一(多个方法的实现), 其问题在于将相同的逻辑在所有方法中都重复实现了一遍, 同时每个类型的函数名都不一样, 也增加了函数调用的难度.
方案二(通过判断类型), 这样确实将大小比较的逻辑放到一起来, 但返回值也变成interface
了, 函数的调用方接到返回时还需要进行一次转型.
而有了泛型之后, 函数就可以这样写了:
func minNew[T int|float32](a, b T) T {
if a < b {
return a
} else {
return b
}
}
是不是简洁很多了. 在线运行
相信你也注意到了, 上面函数中有这样一段内容[T int|float32]
. 这段是对T
这个泛型的约束, 指定这个泛型具有哪些特性的.如果在上面的约束中加上interface
那就回报错了, 因为interface
是无法进行大小比较的.
泛型及其约束的使用方式如下:
// any 同 interface{}
type anyDemo[T any] []T
// comparable 用来标识所有可以使用 ==/!= 进行比较的类型
type anyDemo[T comparable] []T
// 限制泛型 T 为 int|int32|float32 其中一个
type anyDemo[T int|int32|float32] []T
/*
约束前添加 "~"符合, 意为底层类型
例如定义类型: type myInt int
myInt 类型变量底层类型为 int, 但仍然是两个不同的类型
若泛型约束为 int, 那么就不能接受 myInt 类型的变量
而泛型约束为 ~int, 就可以接受 myInt 类型的变量
*/
type anyDemo[T ~int|int32] []T
// 泛型类型定义方法
func (m *anyDemo[T]) Push(v T) *anyDemo[T] {
*m = append(*m, v)
return m
}
// 方法中使用
func funcDemo[T any](a, b T) T{}
// 结构体中使用泛型
type structDemo[T1, T2 any] struct{
t1 T1
arr []T2
}
// 泛型约束也可以通过接口进行定义, 以方便使用
// 定义不同类型的集合
type inter1 interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~string
}
同时也增加了支持泛型的系统库:
- goland.org/x/exp/constraints: 对泛型代码的约束
- golang.org/x/exp/slices: 切片操作
- golang.org/x/exp/maps: map 操作
完了, 就这么点玩意