go排序首选sort包:基础类型用sort.ints等高效安全,自定义逻辑用sort.slice并注意nil判空、时间比较用after/before、多字段靠短路判断。

Go 里排序切片,别手写快排或冒泡——sort 包开箱即用,安全、高效、语义清晰。你唯一要纠结的,是选哪个函数、怎么写比较逻辑、以及哪些边界情况会悄悄 panic。
sort.Ints / sort.Strings 等内置函数只适用于基础类型切片
当你处理的是 []int、[]string、[]float64 这类标准类型切片时,直接用对应函数最快,它们底层做了特化优化,比 sort.Slice 略快且更安全(不会因闭包捕获错误变量引发隐患)。
注意:sort.Ints 和 sort.Strings 只支持升序,不接受自定义规则。比如想按字符串长度排序 []string,就不能用 sort.Strings,必须退回 sort.Slice。
-
sort.Ints(nums)→ 数值升序;sort.Strings(words)→ UTF-8 字节序字典升序(非本地化,中文按 Unicode 码点排) - 降序不能加负号或取反,得套
sort.Sort(sort.Reverse(sort.IntSlice(nums)));sort.IntSlice是类型别名,不是函数 - 传入含
nil元素的[]*string会直接 panic,这些函数不做空值防护
sort.Slice 的闭包里必须用索引访问,且所有 nil 都得手动判
sort.Slice 是结构体、指针切片、多字段排序等场景的主力。它第一个参数是切片本身(如 []Person),不是指针(&[]Person 会编译报错);闭包中 i、j 是下标,不是元素值。
- 对
[]*Person排序时,people[i]可能为nil,直接写people[i].Name就 panic。必须先解构再三支判断:a, b := people[i], people[j],然后分a == nil && b == nil、a == nil、b == nil处理 - 嵌套字段如
a.Address.City,得逐层判空:a.Address != nil && a.Address.City != "" - 时间比较别用
a.CreatedAt > b.CreatedAt——time.Time不支持运算符,改用a.CreatedAt.After(b.CreatedAt)或a.CreatedAt.Before(b.CreatedAt)
多字段排序必须在一个闭包里完成,靠短路判断控制优先级
两次调用 sort.Slice 不会叠加效果,后一次会破坏前一次顺序。多字段(如先按状态、再按时间倒序)必须在一个 func(i, j int) bool 里写完。
- 写法核心是短路:前面字段不等就直接返回,相等才比下一个。例如:
if a.Status != b.Status { return a.Status ,然后接 <code>return a.CreatedAt.After(b.CreatedAt) - 所有分支必须有明确返回值。如果两个元素所有字段都相等,但闭包没写兜底
return false,行为未定义(可能 panic 或结果错乱) - 忽略大小写排序字符串?别用
sort.Strings,改用sort.Slice(words, func(i, j int) bool { return strings.ToLower(words[i])
稳定性不是默认选项,需要时必须显式选 sort.SliceStable
sort.Slice 底层是 pdqsort(混合快排),不保证稳定性 —— 即相等元素的原始相对顺序可能被打乱。如果你依赖这个顺序(比如分页合并后保持插入顺序、按分类分组再内部排序),就得换 sort.SliceStable。
-
sort.SliceStable用归并排序,额外消耗O(n)空间,但保留相等元素的原始位置关系 - “相等”由你的闭包定义:只要
less(i,j) == false && less(j,i) == false,就视为相等。别指望 runtime 自动识别业务意义上的“相同” - 没有
sort.Stable对应的sort.IntsStable等快捷函数,基础类型要稳定排序也得走sort.SliceStable+ 闭包
最容易被忽略的一点:所有 sort 函数都是原地修改,不返回新切片。如果原始数据还要用,记得提前 append([]T(nil), s...) 拷贝一份 —— 尤其在 HTTP handler 或并发场景里,共享切片被意外重排会导致隐蔽 bug。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











