Go sort包提供三条排序路径:基础类型用预置函数(如sort.Strings)、自定义用sort.Slice、复用逻辑用sort.Interface;选错路径会导致冗余、性能浪费或稳定性丢失。

Go 的 sort 包不提供“通用排序函数”,而是通过三种明确路径实现排序:基础类型用预置函数、快速自定义用 sort.Slice、复用逻辑用 sort.Interface。选错路径会导致代码冗余、性能浪费或稳定性丢失。
用 sort.Ints / sort.Strings 等预置函数处理基础切片
这些函数专为 []int、[]string、[]float64 优化,语义清晰、零闭包开销、不可被误写错逻辑。
- 仅支持升序;降序必须配合
sort.Reverse或换用sort.Slice - 不接受结构体、指针切片或含
nil元素的切片——会 panic -
sort.IntsAreSorted和sort.StringsAreSorted可用于校验结果,适合测试断言
示例:sort.Strings(words) 按字典序升序;想按长度降序?不能用它,得切到 sort.Slice。
用 sort.Slice 实现任意切片的快速自定义排序
Go 1.8+ 推荐首选,无需定义新类型、不污染业务结构,闭包内直接写比较逻辑。
立即学习“go语言免费学习笔记(深入)”;
- 比较函数签名是
func(i, j int) bool,返回true表示i应排在j前面(即“i 在 j 左边”) - 多字段排序用条件分支:先比主字段,相等再比次字段,避免用
&&连写导致短路失效 - 切片必须可寻址:不能传字面量如
sort.Slice([]int{1,2}, ...),会编译报错
示例(结构体双字段):sort.Slice(people, func(i, j int) bool { if people[i].Age != people[j].Age { return people[i].Age people[j].Name })
用 sort.Interface 封装可复用、可测试的排序行为
当你需要在多个地方用同一规则(如“按价格降序”)、或想把排序能力绑定到类型上时,才值得实现 Len/Less/Swap 三个方法。
- 必须定义新类型(如
type ByPrice []Product),不能直接在原 struct 上实现 -
Less方法里禁止修改数据,只做比较;Swap必须真正交换底层数组元素 - 若需稳定排序(相同键值保持原始顺序),必须用
sort.Stable或sort.SliceStable,普通sort.Sort不保证
示例:sort.Sort(ByPrice(products)) —— 后续所有同类型排序都可复用 ByPrice 类型。
别忽略稳定性与数组转换这两个隐藏坑
多数人只记得“排序是原地的”,却忘了两个关键细节:
-
sort.Slice不稳定;当排序键重复(如多人同分),原始顺序可能被打乱。需要保持相对顺序?必须换sort.SliceStable - Go 中数组(如
[5]int)不是切片,sort所有函数都不接受数组。正确做法是传arr[:]转为切片,底层共享内存,原数组同步更新
稳定性不是“锦上添花”,而是业务逻辑依赖项——比如先按状态分组、再按时间排序,第二级就靠原始顺序兜底。










