go1.20 变化

Free Member

为了提高Go的广泛适用性,给少数极端场景预留更多可发挥的空间。新版Go可以由程序员自己管理内存了。谁申请,谁释放。

当然,目前还没在正式发布版本中支持,需要特殊参数启动选项。参考代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import (
	"arena"
)

type T struct {
	val int
}

func main() {
	a := arena.New()
	var ptrT *T
	a.New(&ptrT)
	ptrT.val = 1

	var sliceT []T
	a.NewSlice(&sliceT, 100)
	sliceT[99].val = 4

	a.Free()
}

参考阅读:

https://zhuanlan.zhihu.com/p/583572024

String和[]Byte性能转换

Go官方准备在 1.20 中把这两个类型 SliceHeader 和 StringHeader 废弃掉,避免大家的误用。废弃就废弃吧,但是也得提供相应的替代方法才行。这不又增加了几个方法 String 、 StringData 、 Slice 和 SliceData 。用来做这种性能转换。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 返回一个Slice,它的底层数组自ptr开始,长度和容量都是len
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
// 返回一个指针,指向底层的数组
func SliceData(slice []ArbitraryType) *ArbitraryType
// 生成一个字符串,底层的数组开始自ptr, 长度是len
func String(ptr *byte, len IntegerType) string
// 返回字符串底层的数组
func StringData(str string) *byte

// 那么最新的魔法写法:
func StringToBytes(s string) []byte {
    return unsafe.Slice(unsafe.StringData(s), len(s))
}

func BytesToString(b []byte) string {
    return unsafe.String(&b[0], len(b))
}

go1.18版本最大的变化是开始支持泛型。

1.18开始支持泛型

关于泛型,参考阅读:

https://blog.csdn.net/nihaihaoma/article/details/125601630

关键字any的引入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 查看当前项目下的interface{}使用情况
$find . -name "*.go"|xargs grep "interface{}"

# 查看此次替换会影响到的源文件列表
$gofmt -l -r 'interface{} -> any' .

# 实施全局替换
$gofmt -w -r 'interface{} -> any' .

## 注意:gofmt不会替换注释中的interface{}

# 最后,可以使用下面名了检查替换情况
$find . -name "*.go"|xargs grep "interface{}"

go1.17开始支持切片转换为数组指针

支持将切片转换为数组指针

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 数组可以转换成切片
func array2slice() {
 var a = [5]int{11, 12, 13, 14, 15}
 var b = a[0:len(a)] // or var b = a[:]
 b[1] += 10
 fmt.Printf("%v\n", b) // [11 22 13 14 15]
}

// 之前版本不允许切片转换成数组
func slice2array() {
 var b = []int{11, 12, 13}
 var a = [3]int(b) // 报错:cannot convert b (type []int) to type [3]int
 fmt.Printf("%v\n", a)
}

// go 1.17版本开始,可以切片转数组指针
func slice2arrayptr() {
 var b = []int{11, 12, 13}
 var p = (*[3]int)(b) // 这里必须是指针类型
 p[1] = p[1] + 10
 fmt.Printf("%v\n", b) // [11 22 13]
}

unsafe包新增了两个“语法糖”函数

1
2
3
// $GOROOT/src/unsafe.go
func Add(ptr Pointer, len IntegerType) Pointe
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType

(完)