Go 1.25发布:功能和创新

Go 1.25:具有稳定性和性能改进的主要更新

image.png|300

注:本文核心内容由大语言模型生成,辅以人工事实核查与结构调整。

Go 团队正式发布 Go 1.25

Go 团队在 2025 年 8 月 按计划发布了 Go 1.25,此版本紧随 Go 1.24 六个月后到来。本次版本主要聚焦于 工具链、运行时和标准库的重大改进。和以往一样,Go 1.25 遵循 Go 1 兼容性承诺,几乎所有现有的 Go 程序都可以继续编译和运行而无需修改。此次发布强调了 Go 对 稳定性和务实演进 的承诺,通过底层改进为开发者带来了“看不见的好处”。


语言变化

Go 1.25 没有引入会直接影响现有 Go 程序的语言改动。这种对稳定性的坚持,是 Go 在生产环境中广受欢迎的关键原因之一。

不过,语言规范中进行了一次内部“清理”:移除了“核心类型(core types)”的概念,改为使用专门的说明文字。虽然此改动对日常编码没有影响,但它简化了语言规范,被视为为 未来泛型演进 铺平道路的一步。


工具

Go 1.25 对工具链进行了大幅增强,提升了效率和可靠性。

Go 命令改进

  • go build -asan 改进
    现在默认在程序退出时进行内存泄漏检测:如果 C 分配的内存未被引用且未释放,会报告错误。
    可通过设置环境变量 ASAN_OPTIONS=detect_leaks=0 来禁用此行为。

  • 减少预构建工具二进制文件
    Go 发行版中将包含更少的预构建工具二进制文件,非构建或测试过程需要的工具,现在会由 go tool 按需构建并运行。

  • 新增 go.mod ignore 指令
    允许指定某些目录在匹配 all./… 等包模式时被忽略。
    这些文件依然会包含在模块 zip 包中。此功能对 大型 monorepo 项目 特别有用。

  • 新增 go doc -http 选项
    启动本地文档服务器,并在浏览器中打开所请求对象的文档,提升了 离线文档访问体验

  • 新增 go version -m -json 选项
    输出嵌入在 Go 二进制文件中的 runtime/debug.BuildInfo 结构的 JSON 编码。

  • 模块子目录支持
    go 命令现在支持将 仓库的子目录 作为模块根目录,通过以下语法实现更灵活的模块路径解析:

    1
    <meta name="go-import" content="root-path vcs repo-url subdir">

    这解决了 monorepo 管理和自定义 vanity import 的长期难题。

  • 新增 work 包模式
    新的 work 包模式匹配工作区(原 main 模块)中的所有包,无论是单模块模式还是工作区模式。

  • 不再自动写入 toolchain 行
    go 命令在更新 go.modgo.work 文件时,不再自动添加指定当前版本的 toolchain 行。


Vet 分析器

go vet 新增了两个静态检查器:

  • **waitgroup**:报告错误放置的 sync.WaitGroup.Add 调用,例如在 goroutine 内调用。

  • **hostport**:检测使用 fmt.Sprintf("%s:%d", host, port) 进行 net.Dial 的情况,这种写法可能无法正确处理 IPv6,建议改用 net.JoinHostPort

这些静态检查有助于避免常见的 并发网络编程 错误。

运行时(Runtime)

Go 1.25 带来了关键的运行时改进,包括 容器感知的 GOMAXPROCS 和一个 新的实验性垃圾回收器 等。

容器感知的 GOMAXPROCS

  • 默认行为变更:以前,GOMAXPROCS 默认值为 runtime.NumCPU,即逻辑 CPU 的数量。

  • Linux 下的新行为:运行时现在会考虑当前进程所在 cgroup 的 CPU 带宽限制。如果该限制(通常对应 Kubernetes 的 “CPU limit” 选项)小于逻辑 CPU 数量,那么 GOMAXPROCS 会默认取这个较小值。

    • 这样能让 Go 应用在容器化环境(如 Kubernetes)中更智能、更高效,避免资源浪费或性能瓶颈。

例如,在一个设置了 CPU 限制的 Docker 容器中运行 Go 1.25 程序:

1
2
3
4
docker run --cpus=4 golang:1.25-alpine go run /app/nproc.go
# 输出:
# NumCPU: 8
# GOMAXPROCS: 4

与 Go 1.24 不同,当时 GOMAXPROCS 仍然会是 8。

  • 动态更新:如果逻辑 CPU 数量或 cgroup 的 CPU 限制发生变化,运行时会周期性更新 GOMAXPROCS

  • 禁用机制:如果通过环境变量或调用 runtime.GOMAXPROCS 手动设置过 GOMAXPROCS,上述行为会被禁用;也可以通过 GODEBUG 显式关闭:

    • containermaxprocs=0

    • updatemaxprocs=0

  • 新函数:新增 runtime.SetDefaultGOMAXPROCS,允许恢复运行时的默认值,即重新启用容器感知的行为。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"runtime"
)

func main() {
// 通过环境变量设置
// GOMAXPROCS=2 go run nproc.go
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0))

// 手动修改
runtime.GOMAXPROCS(4)
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0))

// 恢复默认值
runtime.SetDefaultGOMAXPROCS()
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0))
}

运行结果(假设宿主机有 8 个逻辑 CPU):

1
2
3
GOMAXPROCS: 2
GOMAXPROCS: 4
GOMAXPROCS: 8

此行为仅在 go.mod 文件声明 Go 版本 1.25 或更高时生效。


新的实验性垃圾回收器(Green Tea GC)

  • Go 1.25 引入了一个 实验性垃圾回收器,代号 Green Tea GC,可通过构建时设置环境变量 GOEXPERIMENT=greenteagc 启用。

  • 该 GC 设计用于提升 小对象的标记和扫描性能,改进局部性并提高 CPU 可扩展性。

  • 官方预计,在 GC 使用频繁的实际项目中,GC 开销可减少 **10–40%**。

    • 例如,Josh Baker 报告在他的项目 Tile38 上启用 Green Tea GC 后,GC 开销减少了 **35%**。
  • 该设计仍在演进中,鼓励用户反馈。


Trace Flight Recorder

  • 新增 runtime/trace.FlightRecorder API,用于轻量级捕获运行时执行跟踪。

  • 它会持续记录数据到 内存环形缓冲区,维护一个滑动窗口的执行历史。

  • 当发生重要事件时,程序可以调用 FlightRecorder.WriteTo 将最近几秒的跟踪数据保存到文件。

    • 生成的跟踪文件更小,更适合在 生产环境中调试罕见或间歇性问题。
  • FlightRecorder 可配置保留时长和缓冲区大小。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
"fmt"
"math/rand"
"os"
"runtime/trace"
"time"
)

func main() {
cfg := trace.FlightRecorderConfig{
MinAge: 5 * time.Second,
MaxBytes: 3 << 20, // 3MB
}
rec := trace.NewFlightRecorder(cfg)
rec.Start()
defer rec.Stop()

done := make(chan struct{})
go func() {
defer close(done)
const n = 1 << 20
var s []int
for range n {
s = append(s, rand.IntN(n))
}
fmt.Printf("done filling slice of %d elements\n", len(s))
}()
<-done

file, _ := os.Create("/tmp/trace.out")
defer file.Close()
n, _ := rec.WriteTo(file)
fmt.Printf("wrote %dB to trace file\n", n)

fmt.Println("Use 'go tool trace /tmp/trace.out' to view the trace.")
}

其他运行时改进

  • 未处理 panic 输出调整:对于被 recover 后又 repanic 的情况,错误消息不再重复打印 panic 值,而是显示 [recovered, repanicked]

  • Linux VMA 名称标注:在支持的 Linux 内核上,Go 运行时会为匿名内存映射添加用途标注(例如 [anon: Go: heap]),可通过 GODEBUG=decoratemappings=0 禁用。

  • 并发清理runtime.AddCleanup 注册的清理函数现在会并发执行,更适合高负载场景。

  • 终结器/清理诊断:新增 GODEBUG=checkfinalizers=1,用于诊断常见的终结器和清理问题,并报告队列长度。

  • 互斥锁剖析改进:运行时内部锁的竞争剖析信息现在能正确指向导致延迟的临界区结尾,与 sync.Mutex 的行为一致。


编译器(Compiler)

Go 1.25 的编译器带来了重要修复和性能优化。

Nil 指针 Bug 修复

  • 修复了 Go 1.21 引入的编译器 Bug:该 Bug 可能会导致 nil 指针检查被错误延迟
  • 之前一些本应 panic 的程序可能会错误地继续执行,现在会 正确触发 nil 指针异常

示例:

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "os"

func main() {
f, err := os.Open("nonExistentFile")
name := f.Name() // Go 1.25 会在此正确 panic
if err != nil {
return
}
println(name)
}

解决方法:应立即在返回错误的语句后检查 err


DWARF5 调试信息

  • 编译器和链接器现在默认生成 DWARF v5 调试信息。

  • 这样能减少 Go 二进制文件的调试信息空间占用,并缩短链接时间(尤其是大型项目)。

  • 可通过 GOEXPERIMENT=nodwarf5 禁用 DWARF5。


更快的切片分配

  • 编译器现在可以在更多情况下 将切片的底层数组分配到栈上,提升性能。

  • 但这可能加剧使用错误 unsafe.Pointer 的问题。

    • 可使用 bisect 工具并加上 -compile=variablemake 选项来定位问题。
  • 所有新的栈分配也可以通过以下选项关闭:

1
-gcflags=all=-d=variablemakehash=n

链接器 (Linker)

Go 1.25 的链接器新增了一个命令行选项:

  • 链接器现在接受 -funcalign=N 命令行选项,用于指定函数入口的对齐方式。默认值依然依赖平台,在本次版本中保持不变。

标准库 (Standard Library)

Go 1.25 带来了大量标准库改进,包括新包、实验性功能,以及在多个模块上的增强。


新增 testing/synctest

  • testing/synctest 包在 Go 1.24 中作为实验性功能引入,在 Go 1.25 中已 正式可用

  • 它为并发代码测试提供了强大支持。
    Test 函数会在一个隔离的 “bubble” 中运行测试函数,在这里时间是虚拟化的,这使得 time 包的函数运行在一个假时钟上。
    当 bubble 中所有 goroutine 都被阻塞时,时钟会瞬间前进。这使得测试超时场景时无需真正等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 示例:测试超时不再需要等待 60 秒
package main

import (
"errors"
"fmt"
"testing"
"time"

"golang.org/x/sync/synctest" // Renamed from "sync/synctest" in source for illustration
)

// Read reads a value from the input channel and returns it.
// Timeouts after 60 seconds.
func Read(in chan int) (int, error) {
select {
case v := <-in:
return v, nil
case <-time.After(60 * time.Second):
return 0, errors.New("timeout")
}
}

func TestReadTimeout(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
ch := make(chan int)
_, err := Read(ch)
if err == nil {
t.Fatal("expected timeout error, got nil")
}
fmt.Println("TestReadTimeout PASS") // Illustrative print
})
}
// This test would pass instantly without waiting 60 seconds
  • Wait 函数:等待当前 bubble 中所有 goroutine 阻塞后再恢复执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 示例:确保内部 goroutine 已经启动并阻塞
package main

import (
"fmt"
"testing"
"time"

"golang.org/x/sync/synctest"
)

func TestWait(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
var innerStarted bool
done := make(chan struct{})
go func() {
innerStarted = true
time.Sleep(time.Second)
close(done)
}()
// Wait for the inner goroutine to block on time.Sleep.
synctest.Wait()
// innerStarted is guaranteed to be true here.
fmt.Printf("inner started: %v\n", innerStarted)
<-done
})
}
// Output: inner started: true
  • Go 1.24 的实验性函数 Run 已废弃,推荐使用 Test

实验性 encoding/json/v2

  • Go 1.25 包含一个 新的实验性 JSON 实现,需在构建时设置 GOEXPERIMENT=jsonv2 才能启用。

  • 这是对 encoding/json 包的一次重大修订,并新增了 encoding/json/jsontext 包用于更底层的 JSON 语法处理。

  • 新实现提供了 显著更快的解码性能,编码性能大多数情况下保持不变,解决了长期存在的性能瓶颈。

  • 它支持通过 MarshalToFuncUnmarshalFromFunc 为任意类型实现自定义的序列化和反序列化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 示例:把布尔值或布尔风格字符串 ("on"/"off") 转换为 ✓ 或 ✗
package main

import (
"fmt"
"encoding/json"
"github.com/go-json-experiment/jsonv2" // Updated import for v2
"github.com/go-json-experiment/jsonv2/jsontext"
)

func main() {
// Marshals boolean values to ✓ or ✗.
boolMarshaler := jsonv2.MarshalToFunc(
func(enc *jsontext.Encoder, val bool) error {
if val {
return enc.WriteToken(jsontext.String("✓"))
}
return enc.WriteToken(jsontext.String("✗"))
},
)

// Marshals boolean-like strings to ✓ or ✗.
strMarshaler := jsonv2.MarshalToFunc(
func(enc *jsontext.Encoder, val string) error {
if val == "on" || val == "true" {
return enc.WriteToken(jsontext.String("✓"))
}
if val == "off" || val == "false" {
return enc.WriteToken(jsontext.String("✗"))
}
// SkipFunc tells Go to skip the current marshaler and move to the next.
return jsonv2.SkipFunc
},
)

// Combine custom marshalers with JoinMarshalers.
marshalers := jsonv2.JoinMarshalers(boolMarshaler, strMarshaler)

// Marshal some values.
vals := []any{true, "off", "hello"}
data, err := jsonv2.Marshal(vals, jsonv2.WithMarshalers(marshalers))
fmt.Println(string(data), err)
}
// Output: ["✓","✗","hello"] <nil>

  • encoding/json/v2 的设计仍在演进中,鼓励开发者提供兼容性反馈。

sync.WaitGroup.Go

  • 新增 WaitGroup.Go 方法,简化了常见的 goroutine 启动与计数模式。

  • 它会自动调用 Add、在 goroutine 中执行函数,并在结束时调用 Done,避免冗余的模板代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 示例:使用 wg.Go 启动多个 goroutine
package main

import (
"fmt"
"sync"
)

func main() {
var wg sync.WaitGroup
wg.Go(func() {
fmt.Println("go is awesome")
})
wg.Go(func() {
fmt.Println("cats are cute")
})
wg.Wait()
fmt.Println("done")
}
/*
Output (order may vary for "go is awesome" and "cats are cute"):
cats are cute
go is awesome
done
*/

os.Root 增强

  • os.Root 类型用于限制文件系统操作范围,现在新增了多个方法(对应 os 包已有的函数),让文件操作更安全。

  • 新增方法包括:ChmodChownChtimesLchownLinkMkdirAllReadFileReadlinkRemoveAllRenameSymlinkWriteFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 示例:在受限目录下执行文件操作(权限修改、读写、重命名、符号链接等)
package main

import (
"fmt"
"os"
"syscall"
"time"
)

func main() {
// This example assumes a "data" directory exists and has a "01.txt" file.
// In a real scenario, you'd handle directory/file creation and errors.
// For demonstration, these files might need to be created manually or programmatically.

// Example: Chmod
root, _ := os.OpenRoot("data")
defer root.Close() // Ensure the root is closed

// Create a dummy file for Chmod example if it doesn't exist
root.WriteFile("01.txt", []byte("hello"), 0644)

root.Chmod("01.txt", 0600)
finfo, _ := root.Stat("01.txt")
fmt.Println("Chmod:", finfo.Mode().Perm()) // Output: -rw-------

// Example: Chown (requires appropriate permissions and user IDs)
// root.Chown("01.txt", 1000, 1000)
// finfo, _ = root.Stat("01.txt")
// stat := finfo.Sys().(*syscall.Stat_t)
// fmt.Printf("Chown: uid=%d, gid=%d\n", stat.Uid, stat.Gid)

// Example: MkdirAll
const dname = "path/to/secret"
root.MkdirAll(dname, 0750)
finfo, _ = root.Stat(dname)
fmt.Printf("MkdirAll: %s %s\n", dname, finfo.Mode()) // Output: path/to/secret drwxr-x---

// Example: Symlink & Readlink
const lname = "symlink.txt"
root.Symlink("01.txt", lname)
lpath, _ := root.Readlink(lname)
fmt.Printf("Symlink/Readlink: %s -> %s\n", lname, lpath) // Output: symlink.txt -> 01.txt

// Example: WriteFile & ReadFile
const fname = "go.txt"
root.WriteFile(fname, []byte("go is awesome"), 0644)
content, _ := root.ReadFile(fname)
fmt.Printf("WriteFile/ReadFile: %s: %s\n", fname, content) // Output: go.txt: go is awesome

// Example: Rename
const oldname = "01.txt"
const newname = "go_old.txt"
root.Rename(oldname, newname)
_, err := root.Stat(oldname)
fmt.Printf("Rename (old name error): %v\n", err) // Output: stat data/01.txt: no such file or directory
finfo, _ = root.Stat(newname)
fmt.Printf("Rename (new name): %s\n", finfo.Name()) // Output: go_old.txt
}
  • os.DirFSos.Root.FS 返回的文件系统现在实现了新接口 io/fs.ReadLinkFS,支持 ReadLinkLstat

reflect.TypeAssert

  • 新增 reflect.TypeAssert 函数,允许将 reflect.Value 直接转换为目标类型。

  • 这类似于对 Value.Interface 结果做类型断言,但 避免了额外的内存分配(因为不需要装箱为接口)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 示例:反射值直接转换为结构体
package main

import (
"fmt"
"reflect"
)

type Person struct {
Name string
Age int
}

func main() {
alice := &Person{"Alice", 25}
// Given a reflection Value...
aliceVal := reflect.ValueOf(alice).Elem()
// ...convert it back to the Person type using TypeAssert.
person, _ := reflect.TypeAssert[Person](aliceVal)
fmt.Printf("Name: %s, Age: %d\n", person.Name, person.Age)
}
// Output: Name: Alice, Age: 25

testing 包改进

  • **新方法 T.AttrB.AttrF.Attr**:
    可向测试日志输出任意键值对属性,常用于关联 issue 链接或描述,特别适合 -json 模式下的自动化处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 示例:输出带 issue 和 description 的测试日志
package main

import "testing"

func TestAttrs(t *testing.T) {
t.Attr("issue", "demo-1234")
t.Attr("description", "Testing for the impossible")
if 21*2 != 42 {
t.Fatal("What in the world happened to math?")
}
}
/*
Output (partially):
=== RUN TestAttrs
=== ATTR TestAttrs issue demo-1234
=== ATTR TestAttrs description Testing for the impossible
--- PASS: TestAttrs (0.00s)
*/
  • **新方法 Output**:
    提供一个 io.Writer,写入的内容与 TB.Log 相同,但不带文件和行号。
    这便于将应用日志直接重定向到测试输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 示例:使用 slog 日志写入测试输出
package main

import (
"log/slog"
"testing"
)

func TestLog(t *testing.T) {
t.Log("test message 1")
t.Log("test message 2")
appLog := slog.New(slog.NewTextHandler(t.Output(), nil))
appLog.Info("app message")
}
/*
Output (partially):
=== RUN TestLog
main_test.go:12: test message 1
main_test.go:13: test message 2
time=... level=INFO msg="app message"
--- PASS: TestLog (0.00s)
*/
  • AllocsPerRun 在并行测试中调用会 panic,避免因并发导致的结果不稳定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 示例:并行测试下调用 AllocsPerRun 会 panic
package main

import "testing"

func TestAllocs(t *testing.T) {
t.Parallel() // Enables parallel execution
allocs := testing.AllocsPerRun(100, func() {
var s []int
// Do some allocations.
for i := range 1024 {
s = append(s, i)
}
})
t.Log("Allocations per run:", allocs) // This will now panic in Go 1.25
}
/*
Output (Go 1.25):
=== RUN TestAllocs
=== PAUSE TestAllocs
=== CONT TestAllocs
--- FAIL: TestAllocs (0.00s)
panic: testing: AllocsPerRun called during parallel test [recovered, repanicked]
*/

log/slog.GroupAttrs

  • 新增 slog.GroupAttrs 函数,允许从 []slog.Attr 创建分组属性。

  • 解决了之前 slog.Group 不能直接接收切片的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 示例:分组属性输出
package main

import (
"log/slog"
"os"
)

func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

// Before GroupAttrs, this would cause a compilation error:
// attrs := []slog.Attr{
// slog.Int("value", 1000),
// slog.String("currency", "USD"),
// }
// logger.Info("deposit", slog.Bool("ok", true), slog.Group("amount", attrs...),)

// With slog.GroupAttrs
attrs := []slog.Attr{
slog.Int("value", 1000),
slog.String("currency", "USD"),
}
logger.Info("deposit", slog.Bool("ok", true), slog.GroupAttrs("amount", attrs...),)
}
// Output: time=... level=INFO msg=deposit ok=true amount.value=1000 amount.currency=USD

hash.Cloner 接口

  • 新增 hash.Cloner 接口,允许哈希函数克隆当前状态。

  • 标准库所有 hash.Hash 实现现在都支持 Cloner(包括 MD5、SHA-1、SHA-3、FNV-1、CRC-64 等)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 示例:克隆 SHA3 状态后继续计算
package main

import (
"fmt"
"reflect"

"golang.org/x/crypto/sha3" // Example with sha3
)

func main() {
h1 := sha3.New256()
h1.Write([]byte("hello"))

clone, _ := h1.Clone() // Clone the current state of h1
h2 := clone.(*sha3.SHA3)

// h2 has the same state as h1. Further writes to each will result in the same hash.
h1.Write([]byte("world"))
h2.Write([]byte("world"))

fmt.Printf("h1: %x\n", h1.Sum(nil))
fmt.Printf("h2: %x\n", h2.Sum(nil))
fmt.Printf("h1 == h2: %t\n", reflect.DeepEqual(h1.Sum(nil), h2.Sum(nil)))
}
// Output:
// h1: ... (same hash)
// h2: ... (same hash)
// h1 == h2: true

其他重要改动

  • archive/tar: Writer.AddFS 现在支持实现了 io/fs.ReadLinkFS 的文件系统中的符号链接。

  • encoding/asn1: UnmarshalUnmarshalWithParamsT61StringBMPString 的解析更一致,可能会拒绝之前接受的错误编码。

  • crypto 包:新增 MessageSigner 接口和 SignMessage 函数。

    • crypto/ecdsacrypto/ed25519 签名性能在 FIPS 140-3 模式下提升 4 倍。

    • crypto/rsa 密钥生成性能提升 3 倍。

    • 在 amd64 平台上,使用 SHA-NI 指令的 SHA-1 哈希性能提升 2 倍。

    • 在 Apple M 系列处理器上,SHA3 哈希性能提升 2 倍。

  • crypto/tls: 更严格遵循规范,默认禁止在 TLS 1.2 中使用 SHA-1 签名算法(可通过 GODEBUG=tlssha1=1 启用)。TLS 服务器现在会优先使用最高支持的协议版本。

  • net:

    • LookupMXResolver.LookupMX 现在返回的 DNS 名称更符合规范,即使名称服务器返回了看似 IP 的字符串。

    • Windows 上 ListenMulticastUDP 支持 IPv6 地址。

    • 支持在 os.File 与网络连接之间转换。

  • net/http: 新增 CrossOriginProtection 类型,实现基于现代浏览器 Fetch metadata 的 CSRF 防护机制,无需使用 Token 或 Cookie。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 示例:防止跨站请求伪造 (CSRF) 的中间件
package main

import (
"fmt"
"io"
"log"
"net/http"
)

func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /get", func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "ok\n")
})
mux.HandleFunc("POST /post", func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "ok\n")
})

antiCSRF := http.NewCrossOriginProtection()
antiCSRF.AddTrustedOrigin("https://example.com")
antiCSRF.AddTrustedOrigin("https://*.example.com")

srv := http.Server{
Addr: ":8080",
Handler: antiCSRF.Handler(mux),
}
log.Fatal(srv.ListenAndServe())

// To test, run this Go program and then use curl in another terminal:
// curl --data "ok" -H "sec-fetch-site:same-origin" localhost:8080/post
// Output: ok
// curl --data "ok" -H "sec-fetch-site:cross-site" localhost:8080/post
// Output: cross-origin request detected from Sec-Fetch-Site header
// curl --data "ok" -H "origin:https://evil.com" -H "host:antonz.org" localhost:8080/post
// Output: cross-origin request detected, and/or browser is out of date: Sec-Fetch-Site is missing, and Origin does not match Host
// curl --data "ok" -H "origin:https://example.com" -H "host:antonz.org" localhost:8080/post
// Output: ok
// curl -H "origin:https://evil.com" localhost:8080/get
// Output: ok
}
  • unique: 现在更积极、高效且并行地回收已实习 (interned) 的值,降低大量唯一值缓存应用的内存消耗。

移植与平台支持

Go 1.25 对支持的平台进行了更新和调整:

  • Darwin:Go 1.25 要求 macOS 12 Monterey 或更高版本。对旧版本的支持已被终止,这在 Go 1.24 的发布说明中已提前宣布。

  • Windows:Go 1.25 是 最后一个包含 32 位 windows/arm 移植版本GOOS=windows GOARCH=arm)的版本。该支持计划在 Go 1.26 中被移除。

  • Loong64linux/loong64 移植版本现在支持竞争检测(race detector),能够通过 runtime.SetCgoTraceback 从 C 代码中收集回溯信息,并且可以使用内部链接模式来链接 cgo 程序。

  • RISC-Vlinux/riscv64 移植版本现在支持 plugin 构建模式。此外,GORISCV64 环境变量接受一个新的值 rva23u64,该值会选择 RVA23U64 用户模式应用配置文件


社区反馈

Go 1.25 的发布总体上收到了积极的社区反馈,大家对其关键特性和语言整体发展方向都给予了肯定。

  • 新的 encoding/json/v2 包是亮点功能,引发了广泛关注和期待。开发者们希望它带来性能提升,并支持为外部类型实现自定义的序列化器,从而解决 Go JSON 处理中的长期痛点。由于该 API 仍处于实验阶段,社区呼吁用户积极测试并提供反馈。

  • Go 的稳定性与可维护性继续受到高度赞赏。许多开发者称赞 Go 一贯的向后兼容性,使得十年前的非简单代码依然可以正常构建和运行。这一“杀手级特性”特别受到系统管理员和运维人员的欢迎,因为 Go 提供静态二进制和可预测的资源表现。

  • 关于 Go 文档和生态 的讨论则意见不一。一些人认为第三方模块的文档缺失或过时,但也有人欣赏 pkg.go.dev 上统一规范的文档,并认为 Go 代码本身往往比外部文档更易读,因为语言强调简洁,并且不鼓励深层抽象。

  • 容器感知的 GOMAXPROCS 改动被认为是最有影响力的改进之一,尤其是在 Kubernetes 和 Docker 环境中部署的应用,能够更智能、高效地利用 CPU 资源。

  • sync.WaitGroup.Go 方法广受欢迎,因为它简化了并发编程中的样板代码,提高了代码可读性并减少了常见错误。

  • 实验性的 Green Tea GC 也备受期待,大家希望它能在真实应用中显著降低垃圾回收的开销。

  • 一些小改动,如 更严格的 TLS 处理net.LookupMX 的更新(该更新优先考虑“现实兼容性”,而不是严格遵循 RFC,以更好地应对真实世界的 DNS 服务器行为),普遍获得好评。

  • 总体来看,Go 1.25 被认为是一个“伟大的版本”,它强调 实用主义,而非“华丽的语法糖”,专注于底层的改进,为开发者带来“无形的收益”。这让开发者能够更多地关注业务逻辑,而 Go 负责处理复杂的系统优化。


引用文章与资源链接:

更多内容

最近文章:

随机文章:


更多该系列文章,参考medium链接:

https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a

English post: https://programmerscareer.com/go-1-25/
作者:微信公众号,Medium,LinkedIn,Twitter
发表日期:原文在 2025-08-17 10:34 时创作于 https://programmerscareer.com/zh-cn/go-1-25/
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证

Go AI sdk:为下一代AI应用和代理提供动力 Vibe规范:规范先行的AI开发

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×