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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!