




Go sort包不支持自动推断类型排序,需用sort.Ints/sort.Strings等专用函数排基础类型,或实现sort.Interface接口排自定义类型;所有排序原地进行、稳定、时间复杂度O(n log n)。
Go 标准库的 sort 包不提供“自动推断类型并排序”的泛型接口(在 Go 1.21 之前),所以不能像 Python 的 sorted() 那样直接传任意切片。必须明确类型、实现 sort.Interface,或使用预定义的快捷函数。
sort.Ints / sort.Strings 快速排基础类型切片这是最常用也最安全的方式:针对 []int、[]string、[]float64 等内置类型,sort 包提供了专用函数,内部已封装好比较逻辑,无需手动实现接口。
sort.Ints 只接受 []int,对 []int64 或自定义整数别名会编译报错package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{3, 1, 4, 1, 5}
sort.Ints(nums) // 直接修改 nums
fmt.Println(nums) // [1 1 3 4 5]
names := []string{"zebra", "apple", "banana"}
sort.Strings(names)
fmt.Println(names) // [apple banana zebra]
}
sort.Interface
当切片元素是 struct 或自定义类型时,必须让该类型满足 sort.Interface 接口(即实现 Len()、Less(i,j int) bool、Swap(i,j int) 三个方法)。常见错误是只实现了 Less 却忘了另外两个。
sort.Sort 时传入的也得是指针切片(如 *[]T)——但通常直接用值接收者更简单Less 方法里不能用 == 比较浮点字段(应改用 math.Abs(a-b) )
sort.Slice(见下节),它更轻量package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
// 值接收者实现 sort.Interface
func (p []Person) Len() int { return len(p) }
func (p []Person) Less(i, j int) bool { return p[i].Age < p[j].Age }
func (p []Person) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func main() {
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35},
}
sort
.Sort(people) // 注意:传的是 people(值),不是 &people
fmt.Println(people) // [{Bob 25} {Alice 30} {Charlie 35}]
}
sort.Slice 按任意规则排序(Go 1.8+)这是最灵活的方式:无需定义新类型或实现接口,直接传入切片和一个闭包函数描述比较逻辑。闭包参数 i、j 是索引,返回 true 表示 i 应排在 j 前面。
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"fmt"
"sort"
)
type Product struct {
ID int
Price float64
Name string
}
func main() {
products := []Product{
{1, 19.99, "Laptop"},
{2, 5.49, "Mouse"},
{3, 12.99, "Keyboard"},
}
// 按价格升序
sort.Slice(products, func(i, j int) bool {
return products[i].Price < products[j].Price
})
fmt.Println(products) // [{2 5.49 Mouse} {3 12.99 Keyboard} {1 19.99 Laptop}]
// 按名称长度降序
sort.Slice(products, func(i, j int) bool {
return len(products[i].Name) > len(products[j].Name)
})
}
Go 的 sort 所有函数都是稳定的(相等元素的相对顺序不变),这点和 Python 的 sorted() 一致,但和 C 的 qsort() 不同。需要逆序时,不要写 a > b,而应翻转比较方向——否则可能因浮点误差或自定义逻辑导致不稳定。
sort.Ints 等快捷函数,没有内置逆序版本;需先正序再 sort.Reverse,或改用 sort.Slice
sort.Reverse 接收一个 sort.Interface,返回一个新的反向接口,常配合 sort.Sort 使用sort.Slice 实现逆序更直观:return a > b 就是降序,return a 就是升序
真正容易被忽略的是:当排序键计算成本高(比如每次调用都要解析 JSON 字段),应预先计算并缓存,而不是在 Less 或闭包中重复计算——sort 可能多次调用比较函数。