Go 1.21+ 应使用标准库 slices.Reverse 原地安全反转切片;旧版本需手动双指针;字符串必须转 []rune 再反转,避免 UTF-8 乱码。

slices.Reverse 是 Go 1.21+ 唯一推荐的内置反转方式,它安全、零分配、类型安全,且直接作用于原切片。如果你用的是旧版本(≤1.20),或需要保留原始切片,就得自己动手——但别用 sort.Slice 或 append + 反向遍历,那不是真反转,还容易踩坑。
用 slices.Reverse 前必须确认 Go 版本和导入路径
Go 1.21 起,slices 已是标准库一部分,无需额外安装:
import "slices"
s := []string{"a", "b", "c"}
slices.Reverse(s) // s 变成 ["c", "b", "a"]
常见错误:
- 误写成
import "golang.org/x/exp/slices":这是 1.21 之前的实验包,1.21+ 会编译失败 - 在 Go 1.20 环境下直接 import "slices":报错
cannot find package "slices" - 传入
nil切片:不会 panic,但也不会做任何事(len(nil)是 0,循环不执行)
手动双指针反转必须写对边界条件
适用于所有 Go 版本,且性能最优(O(n/2) 时间、O(1) 空间)。核心是头尾索引同时向中间收缩:
func reverse[T any](s []T) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
关键细节:
立即学习“go语言免费学习笔记(深入)”;
i 比 <code>i 更直观、更少出错;奇数长度时中间元素自动跳过- 必须传
[]T,不是*[]T:slice 本身含底层数组指针,无需解引用 - 如果要保留原切片,先
slices.Clone(s)(1.21+)或copy(make([]T, len(s)), s)(兼容旧版)
别把 sort.Slice 当反转用
sort.Slice(s, func(i, j int) bool { return i > j }) 这种写法看似能“倒序”,但它本质是排序,不是位置交换:
- 对
[]int或[]string结果相同,但语义错误:它按索引大小比较,实际什么也没排 - 对含指针、map、channel 字段的结构体切片,
sort.Slice不动字段内容,而真实反转会严格交换整个 struct 实例位置 - 如果后续逻辑依赖“第 3 个元素原本在末尾”,用
sort就彻底丢失该信息
字符串反转必须转 []rune,不能直接操作 []byte
字符串是 UTF-8 编码,[]byte 反转会拆断多字节字符:
s := "hello世界?" // ❌ 错误:乱码 b := []byte(s) slices.Reverse(b) fmt.Println(string(b)) // "?界世olleh" // ✅ 正确:按字符反转 r := []rune(s) slices.Reverse(r) fmt.Println(string(r)) // "?界世olleh"
注意:slices.Reverse 支持 []rune,但不支持 string 类型本身——必须显式转换。
rune 转换,以及 slices 包在 1.21+ 的路径变更。


















