
Go 1.23 发布于 2024-08-13。它把 Go 1.22 预览的 range-over-function 变成正式语言能力，让标准库和业务代码可以用统一的迭代器约定表达惰性序列。

源码侧 `api/go1.23.txt` 有 158 条公开 API 增量；公开标准库目录新增 `structs`、`unique`。

## 主要变化

### 1. `for range` 支持函数迭代器

Go 1.23 允许 range 表达式是特定签名的函数。迭代器函数通过调用 yield 函数产出值，调用方仍然写 `for v := range seq`。

```go
func Lines(r io.Reader) iter.Seq[string] {
    return func(yield func(string) bool) {
        scanner := bufio.NewScanner(r)
        for scanner.Scan() {
            if !yield(scanner.Text()) {
                return
            }
        }
    }
}

for line := range Lines(r) {
    fmt.Println(line)
}
```

这个能力解决的是“想流式遍历，但又想保留 `range` 语法”的问题。树遍历、分页查询、过滤管道、按需生成序列都可以不用先构造完整 slice。`yield` 返回 false 表示调用方停止迭代，迭代器应尽快返回。

双值迭代器用 `iter.Seq2[K, V]` 表达，适合 map、索引和值、键和值这类场景：

```go
func Pairs(m map[string]int) iter.Seq2[string, int] {
    return func(yield func(string, int) bool) {
        for k, v := range m {
            if !yield(k, v) {
                return
            }
        }
    }
}

for k, v := range Pairs(counts) {
    fmt.Println(k, v)
}
```

选择规则很简单：只有一个值就用 `Seq[V]`，天然有键值或索引值就用 `Seq2[K, V]`。后续 `maps.All`、`maps.Keys`、`maps.Values`、`slices.All` 这类 API 都围绕这套迭代器模型展开。

### 2. 泛型类型别名进入实验预览

类型别名原本不能带类型参数，泛型 API 在拆包和兼容导出名时会受限制。Go 1.23 通过实验开关预览泛型类型别名，让这类表达成为可能：

```go
type Set[T comparable] = map[T]bool
```

它和 `type Set[T comparable] map[T]bool` 不一样。前者是别名，不创建新类型；后者是定义类型，会有自己的方法集和赋值规则。这个差异决定了它更适合 API 组织，而不是给类型增加新行为。

### 3. telemetry 让工具链有可观测数据

Go telemetry 用来统计 Go 命令和工具链的使用、性能和失败情况。默认只在本地记录，用户可以选择打开上传。它的目标不是观察业务程序，而是帮助 Go 团队理解工具链真实使用情况。

对应命令是 `go telemetry`。它可以查看当前模式，也可以切换为本地-only 或上传模式。这个机制关注的是 Go 命令本身，例如某个命令是否频繁失败、某个路径是否性能异常，而不是应用运行期数据。

### 4. `unique` 和 `structs` 新增

`unique` 提供值规范化能力，同样的值可以得到可比较的 handle。

```go
h1 := unique.Make("region-a")
h2 := unique.Make(strings.Clone("region-a"))
fmt.Println(h1 == h2) // true
```

它适合大量重复值的场景，例如标签、枚举字符串、路径片段。比较 handle 比比较完整值更便宜，也能避免重复存储同一份内容。

`structs` 当前很小，主要提供标记类型。它的价值更多在语言和工具链层面：给“结构体布局相关语义”一个标准位置。

## 语言与规范

range 表达式现在可以是特定签名的函数，例如 `func(func(K, V) bool)`。迭代器函数通过调用 yield 函数产生值，调用方可以继续使用熟悉的 `for range` 语法。

泛型类型别名通过 `GOEXPERIMENT=aliastypeparams` 预览，但跨包使用还有限制，真正稳定要看后续版本。

## 工具链与运行时

Go telemetry 用于收集工具链使用和故障统计。默认模式只把计数写在本地，不会上传；用户可以通过 `go telemetry on` 选择上传匿名统计。

`go env -changed`、`go mod tidy -diff`、`go list -m -json` 的字段增强都偏工程实用。`go vet` 新增 `stdversion`，能发现代码引用了高于当前 `go.mod` 版本的标准库符号。

`go mod tidy -diff` 尤其适合检查模块文件是否已经是 tidy 后状态。它不直接改文件，而是输出 diff 并以非零状态表示有差异，适合放进检查脚本。`stdversion` 则把“标准库 API 属于哪个 Go 版本”纳入静态检查，例如模块声明 `go 1.22` 却使用了 Go 1.23 才出现的 API，会被指出。

运行时的 timer 行为调整，`time.Timer` 和 `time.Ticker` 更容易被 GC 回收，减少常见资源泄漏模式。

旧代码里经常为了避免 timer 泄漏写复杂的 stop/drain 模式：

```go
if !timer.Stop() {
    <-timer.C
}
timer.Reset(d)
```

这类代码容易在并发场景里写错，尤其是 channel 是否已经有值、是否会阻塞、是否和其他 goroutine 同时读。Go 1.23 调整后，不再被引用的 timer/ticker 可以被 GC 回收，`Timer` 关联的 channel 也改成无缓冲语义，减少过期时间值残留带来的困惑。仍然持有并复用 timer 时，`Stop` 和 `Reset` 的返回值语义仍要认真处理；变化的重点是“不再引用的 timer/ticker 不应长期拖住资源”。

## 标准库与新增包

新增公开包：

- `unique`：提供值规范化和去重句柄。
- `structs`：提供结构体标记用途的基础类型。

重要变化：

- `slices` 增加更多迭代器相关能力。
- `crypto/tls`、`net/http`、`runtime/trace`、`sync/atomic` 等继续增强。

## 小版本特殊变化

Go 1.23 系列共有 12 个小版本。函数迭代器、telemetry、`unique` 发布后，小版本里能看到 `unique`、runtime/trace、`go/types` 等新路径被继续修正。

这一系列的安全问题主要围绕解析和系统边界。`go/parser`、`go/build/constraint` 面向源码和构建约束解析，影响代码分析器、生成器和构建工具。`encoding/gob`、`database/sql`、`net/http`、`os/exec` 都是典型边界包：反序列化、数据库连接、HTTP 请求、命令执行。`os` 的安全修复通常和文件、权限或平台行为有关。`unique` 出现在 Bug 修复里，说明新引入的规范化值机制也在小版本中继续稳定。

- `go1.23.1` 修复 `encoding/gob`、`go/build/constraint`、`go/parser` 安全问题，同时修 compiler、`go` 命令、runtime、`database/sql`、`go/types`、`runtime/trace`、`unique`。
- `go1.23.2` 修 compiler、cgo、runtime、`maps`、`os/exec`、`time`、`unique`。
- `go1.23.5` 修复 `crypto/x509` 和 `net/http` 安全问题。
- `go1.23.7` 修复 `net/http` 安全问题，并修 reflect、runtime、syscall。
- `go1.23.10` 修复 `net/http` 和 `os` 安全问题。
- `go1.23.11` 修复 `go` 命令安全问题，并修 compiler、linker、runtime。
- `go1.23.12` 修复 `database/sql` 和 `os/exec` 安全问题。

## 参考

- [Go 1.23 Release Notes](https://go.dev/doc/go1.23)
- [Go Release History](https://go.dev/doc/devel/release)
- [Go 1.23 source tag](https://go.googlesource.com/go/+/refs/tags/go1.23.0)
- [api/go1.23.txt](https://go.googlesource.com/go/+/refs/tags/go1.23.0/api/go1.23.txt)

