Go排序切片应优先使用sort包:基础类型用sort.Ints()或sort.Strings()升序,降序需sort.Sort(sort.Reverse(sort.IntSlice(nums)));结构体等复杂类型用sort.Slice()配闭包,注意判空、稳定性选择及返回值完备性。

Go 里排序切片,别手写快排,直接用 sort 包 —— 它安全、高效、开箱即用,且对常见类型([]int、[]string)零配置。
基础类型切片怎么升序/降序?
升序直接调 sort.Ints() 或 sort.Strings(),原地改,无返回值;降序不是加个负号,得套 sort.Reverse() 再传给 sort.Sort()。
-
sort.Ints(nums)→ 升序;sort.Strings(words)→ 字典序升序(UTF-8 字节序,非本地化) - 降序写法是:
sort.Sort(sort.Reverse(sort.IntSlice(nums))),注意sort.IntSlice是类型别名,不是函数 -
sort.Reverse()返回一个新对象,必须显式传给sort.Sort(),否则没效果 - 字符串忽略大小写?别用
sort.Strings(),改用sort.Slice()+strings.ToLower()比较
结构体切片怎么按字段排序?
用 sort.Slice() 配闭包,别实现 sort.Interface —— 除非你要复用同一套逻辑多次或导出为公共类型。
- 第一个参数是切片本身(
[]Person),不是指针(&[]Person会编译报错) - 闭包里
i、j是下标,不是元素值;别写成p[i].Name < p[0].Name这种硬编码 - 多字段混排(如先按状态、再按时间倒序)必须在一个闭包里完成,用短路判断:
if a.Status != b.Status { return a.Status < b.Status },然后才比a.CreatedAt.After(b.CreatedAt) -
time.Time不能用>/<直接比较,得用.Before()或.After()
nil 元素或空字段导致 panic 怎么办?
sort.Slice() 不做空值防护,一解引用就崩。所有可能为 nil 的字段,必须在闭包里手动判空。
立即学习“go语言免费学习笔记(深入)”;
- 对
[]*Person排序时,people[i]可能是nil,得先a, b := people[i], people[j],再分三支判断:a == nil && b == nil、a == nil、b == nil - 嵌套字段如
a.Address.City,得逐层判空:a.Address != nil && a.Address.City != "" - 空值放前还是放后,由你定;
sort.Slice()不替你决策
什么时候该用 sort.SliceStable()?
当相等元素的原始顺序必须保留时,比如分页合并、按分类分组后再内部排序,就得换 sort.SliceStable()。
-
sort.Slice()底层是类快排,不保证稳定性;sort.SliceStable()用归并排序,额外消耗O(n)空间 - 稳定性只在“比较结果相等”时起作用,比如两个
Age == 30的人,谁在前谁在后取决于原始位置 - 没明确业务要求时,默认用
sort.Slice()更省内存
真正容易被忽略的是:比较函数里所有分支必须有明确返回值,漏掉一种情况(比如两个字段全相等但没写 return false)会导致未定义行为;还有就是 sort.Slice() 原地修改,别忘了需要保留原顺序时提前 copy() 一份。


















