go1.23 新特性
go1.23 新特性
这里面主要记一些语法相关的变化,或者说是我更关注的地方的变化。
Linker
链接器现在不允许使用 //go:linkname 指令引用标准库(包括运行时)中未在定义中标记有 //go:linkname 的内部符号。同样,链接器不允许从汇编代码中引用此类符号。为了向后兼容,现有的 //go:linkname 用法仍然受到支持,这些用法在大型开源代码库中发现。但任何对标准库内部符号的新引用将被禁止。
链接器命令行标志 -checklinkname=0 可用于禁用此检查,适用于调试和实验用途。
当构建动态链接的 ELF 二进制文件(包括 PIE 二进制文件)时,新的 -bindnow 标志可以启用即时函数绑定。
简单来说就是说不允许直接 linkname 一些标准库符号,从下面的示例来看一下。
package main
import (
"fmt"
_ "strings"
_ "unsafe"
)
//go:linkname explode strings.explode
func explode(s string, n int) []string
func main() {
fmt.Println(explode("你好go语言", -1))
}
go 1.13 之前代码是可以正常输出
$ go run .
[你 好 g o 语 言]
尝试使用 go1.23 运行
$ go run .
# linkname
link: main: invalid reference to strings.explode
可以看出程序已经无法正常运行
使用 -checklinkname=0 禁用此检查。
$ go run -ldflags=-checklinkname=0 .
[你 好 g o 语 言]
至于禁用的原因是 “这种使用内部类型的情况是不可持续的”,是的一般这样就是要link一些内部的私有符号,而标准库将这些符号声明为私有的就是为了避免随意的访问,另外大量的访问就会使得私有符号有了公共符号的作用,使得内部的变更变得困难。
range-over-func
Go 1.23 将 (Go 1.22) 的“range-over-func”实验正式纳入语言中。现在,“for-range”循环中的“range”子句可以接受以下类型的迭代器函数作为 range 表达式:
func(func() bool)
func(func(K) bool)
func(func(K, V) bool)
这些类型的函数调用迭代器参数函数来生成“for-range”循环的迭代值。有关详细信息,请参阅 iter 包文档和语言规范。关于动机,参见 2022 年的“range-over-func”讨论。
这块主要是看下 这个 range-over-func 如何使用吧
先看个示例代码吧
package main
import (
"fmt"
"slices"
)
func Backward[E any](s []E) func(func(int, E) bool) {
return func(yield func(int, E) bool) {
for i := len(s) - 1; i >= 0; i-- {
if !yield(i, s[i]) {
return
}
}
}
}
func main() {
s := []string{"hello", "world"}
for i, x := range slices.Backward(s) {
fmt.Println(i, x)
}
// fibo generates the Fibonacci sequence
fibo := func(yield func(x int) bool) {
f0, f1 := 0, 1
for yield(f0) {
f0, f1 = f1, f0+f1
}
}
// print the Fibonacci numbers below 1000:
for x := range fibo {
if x >= 1000 {
break
}
fmt.Printf("%d ", x)
}
}
输出
$ go run .
1 world
0 hello
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
理解有的晦涩,我写一下我对第二个循环的理解吧
for {
if f0 >= 1000 {
break
}
fmt.Printf("%d ", f0)
f0, f1 = f1, f0+f1
}
有的像其他语言的 forEach 循环, 首先 yield 的入参就是 range 返回的内容,而 for 大括号内的内容就是 yield 的方法体,continue 会变成 return true ,而 break 是 return false
其他变更和以上变更详细信息参见Go 1.23 Release Notes
原文 go1-23
本作品采用《CC 协议》,转载必须注明作者和本文链接