sort 包详解
概述
sort 包提供了对切片和用户定义集合进行排序的原语。
核心功能:
- 基本类型切片排序(int、float64、string)
- 自定义类型排序(实现 Interface 接口)
- 使用比较函数排序(Slice、SliceStable)
- 检查切片是否已排序
- 二分查找功能
- 稳定排序支持
重要说明:
- ✅ Go 版本:所有 Go 版本都支持
- ✅ 排序算法:使用 pdqsort(模式防御快速排序)
- ✅ 时间复杂度:最坏情况 O(n log n)
- ⚠️ 稳定性:Sort 不稳定,Stable 稳定
包导入
import "sort"
接口和类型
Interface
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
功能: 任何实现了这三个方法的类型都可以使用 sort 包进行排序。
方法说明:
Len() int- 集合中元素的数量Less(i, j int) bool- 索引 i 的元素是否应该排在索引 j 的元素之前Swap(i, j int)- 交换索引 i 和 j 的元素
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
// ByAge 实现 sort.Interface
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 23},
{"Bob", 25},
{"Charlie", 20},
}
sort.Sort(ByAge(people))
fmt.Println(people)
// [{Charlie 20} {Alice 23} {Bob 25}]
}
IntSlice
type IntSlice []int
功能: 实现了 sort.Interface 的 int 切片类型。
方法:
Len() intLess(i, j int) bool-x[i] < x[j]Swap(i, j int)Sort()- 对切片排序Search(x int) int- 二分查找
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := sort.IntSlice{5, 2, 8, 1, 9}
nums.Sort()
fmt.Println(nums) // [1 2 5 8 9]
// 查找元素
idx := nums.Search(8)
fmt.Printf("8 在索引 %d\n", idx) // 8 在索引 3
}
Float64Slice
type Float64Slice []float64
功能: 实现了 sort.Interface 的 float64 切片类型。
注意:
- NaN 值会被排到最后
Less方法:x[i] < x[j] || (isNaN(x[i]) && !isNaN(x[j]))
方法:
Len() intLess(i, j int) boolSwap(i, j int)Sort()Search(x float64) int
示例:
package main
import (
"fmt"
"math"
"sort"
)
func main() {
nums := sort.Float64Slice{3.14, 1.59, math.NaN(), 2.65}
nums.Sort()
fmt.Println(nums) // [1.59 2.65 3.14 NaN]
}
StringSlice
type StringSlice []string
功能: 实现了 sort.Interface 的 string 切片类型。
方法:
Len() intLess(i, j int) bool-x[i] < x[j]Swap(i, j int)Sort()Search(x string) int
示例:
package main
import (
"fmt"
"sort"
)
func main() {
names := sort.StringSlice{"Charlie", "Alice", "Bob"}
names.Sort()
fmt.Println(names) // [Alice Bob Charlie]
// 查找元素
idx := names.Search("Bob")
fmt.Printf("Bob 在索引 %d\n", idx) // Bob 在索引 1
}
函数详解(按 A-Z 分类)
F
Find
func Find(n int, cmp func(int) int) (i int, found bool)
功能:
使用二分查找找到并返回最小的索引 i,使得 cmp(i) <= 0。
参数:
n int- 搜索范围 [0, n)cmp func(int) int- 比较函数- 返回值 > 0:目标小于当前元素
- 返回值 = 0:目标等于当前元素
- 返回值 < 0:目标大于当前元素
返回值:
i int- 找到的索引,如果不存在返回 nfound bool- 是否找到
要求:
cmp(i) > 0在前缀cmp(i) == 0在中间cmp(i) < 0在后缀
示例:
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
names := []string{"Alice", "Bob", "Charlie", "David"}
target := "Charlie"
idx, found := sort.Find(len(names), func(i int) int {
return strings.Compare(target, names[i])
})
if found {
fmt.Printf("找到 %s 在索引 %d\n", target, idx)
} else {
fmt.Printf("%s 未找到,应插入索引 %d\n", target, idx)
}
}
运行结果:
找到 Charlie 在索引 2
F
Float64s
func Float64s(x []float64)
功能: 对 float64 切片进行升序排序。
参数:
x []float64- 要排序的切片
注意:
- 原地排序
- NaN 排在最后
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := []float64{3.14, 1.59, 2.65, 3.58}
sort.Float64s(nums)
fmt.Println(nums) // [1.59 2.65 3.14 3.58]
}
Float64sAreSorted
func Float64sAreSorted(x []float64) bool
功能: 检查 float64 切片是否已按升序排序。
参数:
x []float64- 要检查的切片
返回值:
bool- 是否已排序
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums1 := []float64{1.59, 2.65, 3.14, 3.58}
nums2 := []float64{3.14, 1.59, 2.65}
fmt.Println(sort.Float64sAreSorted(nums1)) // true
fmt.Println(sort.Float64sAreSorted(nums2)) // false
}
I
Ints
func Ints(x []int)
功能: 对 int 切片进行升序排序。
参数:
x []int- 要排序的切片
注意:
- 原地排序
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{5, 2, 8, 1, 9, 3}
sort.Ints(nums)
fmt.Println(nums) // [1 2 3 5 8 9]
}
IntsAreSorted
func IntsAreSorted(x []int) bool
功能: 检查 int 切片是否已按升序排序。
参数:
x []int- 要检查的切片
返回值:
bool- 是否已排序
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums1 := []int{1, 2, 3, 4, 5}
nums2 := []int{1, 3, 2, 4, 5}
fmt.Println(sort.IntsAreSorted(nums1)) // true
fmt.Println(sort.IntsAreSorted(nums2)) // false
}
I
IsSorted
func IsSorted(data Interface) bool
功能: 检查实现了 Interface 的数据是否已排序。
参数:
data Interface- 要检查的数据
返回值:
bool- 是否已排序
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
people2 := []Person{{"Alice", 20}, {"Charlie", 30}, {"Bob", 25}}
fmt.Println(sort.IsSorted(ByAge(people1))) // true
fmt.Println(sort.IsSorted(ByAge(people2))) // false
}
R
Reverse
func Reverse(data Interface) Interface
功能: 包装一个 Interface 以反转排序顺序(降序)。
参数:
data Interface- 要反转的数据
返回值:
Interface- 反转后的 Interface
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
// 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
fmt.Println(nums) // [5 4 3 2 1]
}
S
Search
func Search(n int, f func(int) bool) int
功能:
使用二分查找找到第一个使 f(i) 为 true 的索引 i。
参数:
n int- 搜索范围 [0, n)f func(int) bool- 条件函数
返回值:
int- 找到的索引,如果不存在返回 n
要求:
f(i)必须为 false 在前缀,true 在后缀
示例:
package main
import (
"fmt"
"sort"
)
func main() {
// 在已排序切片中查找第一个 >= 25 的位置
ages := []int{18, 20, 22, 25, 28, 30}
idx := sort.Search(len(ages), func(i int) bool {
return ages[i] >= 25
})
fmt.Printf("第一个 >= 25 的索引是 %d\n", idx) // 3
if idx < len(ages) {
fmt.Printf("值是 %d\n", ages[idx]) // 25
}
}
SearchFloat64s
func SearchFloat64s(a []float64, x float64) int
功能: 在已排序的 float64 切片中二分查找 x。
参数:
a []float64- 已排序的切片x float64- 要查找的值
返回值:
int- x 的索引,或应插入的位置
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
idx := sort.SearchFloat64s(nums, 3.3)
fmt.Printf("3.3 在索引 %d\n", idx) // 2
idx = sort.SearchFloat64s(nums, 3.0)
fmt.Printf("3.0 应插入索引 %d\n", idx) // 2
}
SearchInts
func SearchInts(a []int, x int) int
功能: 在已排序的 int 切片中二分查找 x。
参数:
a []int- 已排序的切片x int- 要查找的值
返回值:
int- x 的索引,或应插入的位置
示例:
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{1, 3, 5, 7, 9}
idx := sort.SearchInts(nums, 5)
fmt.Printf("5 在索引 %d\n", idx) // 2
idx = sort.SearchInts(nums, 6)
fmt.Printf("6 应插入索引 %d\n", idx) // 3
}
SearchStrings
func SearchStrings(a []string, x string) int
功能: 在已排序的 string 切片中二分查找 x。
参数:
a []string- 已排序的切片x string- 要查找的值
返回值:
int- x 的索引,或应插入的位置
示例:
package main
import (
"fmt"
"sort"
)
func main() {
names := []string{"Alice", "Bob", "Charlie", "David"}
idx := sort.SearchStrings(names, "Charlie")
fmt.Printf("Charlie 在索引 %d\n", idx) // 2
idx = sort.SearchStrings(names, "Carol")
fmt.Printf("Carol 应插入索引 %d\n", idx) // 2
}
Slice
func Slice(x any, less func(i, j int) bool)
功能: 使用提供的比较函数对切片进行排序。
参数:
x any- 要排序的切片(任意类型)less func(i, j int) bool- 比较函数
注意:
- 排序不稳定
- 原地排序
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Charlie", 30},
}
// 按年龄排序
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
fmt.Println(people)
// [{Bob 20} {Alice 25} {Charlie 30}]
}
SliceIsSorted
func SliceIsSorted(x any, less func(i, j int) bool) bool
功能: 使用提供的比较函数检查切片是否已排序。
参数:
x any- 要检查的切片less func(i, j int) bool- 比较函数
返回值:
bool- 是否已排序
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
people2 := []Person{{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}}
sorted := func(p []Person) bool {
return sort.SliceIsSorted(p, func(i, j int) bool {
return p[i].Age < p[j].Age
})
}
fmt.Println(sorted(people1)) // true
fmt.Println(sorted(people2)) // false
}
SliceStable
func SliceStable(x any, less func(i, j int) bool)
功能: 使用提供的比较函数对切片进行稳定排序。
参数:
x any- 要排序的切片less func(i, j int) bool- 比较函数
注意:
- 稳定排序:相等元素保持原始顺序
- 原地排序
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Charlie", 25},
{"David", 20},
}
// 按年龄稳定排序
sort.SliceStable(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
fmt.Println(people)
// [{Bob 20} {David 20} {Alice 25} {Charlie 25}]
// 注意:Bob 和 David 保持了原始顺序
}
Sort
func Sort(data Interface)
功能: 对实现了 Interface 的数据进行排序。
参数:
data Interface- 要排序的数据
注意:
- 不稳定排序
- 原地排序
- 时间复杂度:O(n log n)
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Charlie", 30},
}
sort.Sort(ByAge(people))
fmt.Println(people)
// [{Bob 20} {Alice 25} {Charlie 30}]
}
Stable
func Stable(data Interface)
功能: 对实现了 Interface 的数据进行稳定排序。
参数:
data Interface- 要排序的数据
注意:
- 稳定排序:相等元素保持原始顺序
- 原地排序
- 时间复杂度:O(n log n)
示例:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Charlie", 25},
{"David", 20},
}
sort.Stable(ByAge(people))
fmt.Println(people)
// [{Bob 20} {David 20} {Alice 25} {Charlie 25}]
}
S
Strings
func Strings(x []string)
功能: 对 string 切片进行升序排序。
参数:
x []string- 要排序的切片
注意:
- 原地排序
示例:
package main
import (
"fmt"
"sort"
)
func main() {
names := []string{"Charlie", "Alice", "Bob"}
sort.Strings(names)
fmt.Println(names) // [Alice Bob Charlie]
}
StringsAreSorted
func StringsAreSorted(x []string) bool
功能: 检查 string 切片是否已按升序排序。
参数:
x []string- 要检查的切片
返回值:
bool- 是否已排序
示例:
package main
import (
"fmt"
"sort"
)
func main() {
names1 := []string{"Alice", "Bob", "Charlie"}
names2 := []string{"Charlie", "Alice", "Bob"}
fmt.Println(sort.StringsAreSorted(names1)) // true
fmt.Println(sort.StringsAreSorted(names2)) // false
}
典型示例
示例 1:基本类型排序
package main
import (
"fmt"
"sort"
)
func main() {
// int 排序
nums := []int{5, 2, 8, 1, 9}
sort.Ints(nums)
fmt.Println("Ints:", nums)
// float64 排序
floats := []float64{3.14, 1.59, 2.65}
sort.Float64s(floats)
fmt.Println("Float64s:", floats)
// string 排序
names := []string{"Charlie", "Alice", "Bob"}
sort.Strings(names)
fmt.Println("Strings:", names)
}
运行结果:
Ints: [1 2 5 8 9]
Float64s: [1.59 2.65 3.14]
Strings: [Alice Bob Charlie]
示例 2:自定义类型排序
package main
import (
"fmt"
"sort"
)
type Student struct {
Name string
Score int
Age int
}
type ByScore []Student
func (s ByScore) Len() int { return len(s) }
func (s ByScore) Less(i, j int) bool { return s[i].Score < s[j].Score }
func (s ByScore) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
students := []Student{
{"Alice", 85, 20},
{"Bob", 92, 21},
{"Charlie", 78, 19},
}
sort.Sort(ByScore(students))
fmt.Println("按分数排序:", students)
}
运行结果:
按分数排序:[{Charlie 78 19} {Alice 85 20} {Bob 92 21}]
示例 3:使用 Slice 函数排序
package main
import (
"fmt"
"sort"
)
type Student struct {
Name string
Score int
}
func main() {
students := []Student{
{"Alice", 85},
{"Bob", 92},
{"Charlie", 78},
}
// 使用 Slice 函数,无需实现 Interface
sort.Slice(students, func(i, j int) bool {
return students[i].Score < students[j].Score
})
fmt.Println(students)
}
运行结果:
[{Charlie 78} {Alice 85} {Bob 92}]
示例 4:多字段排序
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Alice", 20},
{"Bob", 25},
}
// 先按姓名,再按年龄排序
sort.Slice(people, func(i, j int) bool {
if people[i].Name != people[j].Name {
return people[i].Name < people[j].Name
}
return people[i].Age < people[j].Age
})
fmt.Println(people)
// [{Alice 20} {Alice 25} {Bob 20} {Bob 25}]
}
示例 5:稳定排序
package main
import (
"fmt"
"sort"
)
type Task struct {
Name string
Priority int
}
func main() {
tasks := []Task{
{"Task1", 2},
{"Task2", 1},
{"Task3", 2},
{"Task4", 1},
}
// 不稳定排序
sort.Slice(tasks, func(i, j int) bool {
return tasks[i].Priority < tasks[j].Priority
})
fmt.Println("不稳定:", tasks)
// 重置
tasks = []Task{
{"Task1", 2},
{"Task2", 1},
{"Task3", 2},
{"Task4", 1},
}
// 稳定排序
sort.SliceStable(tasks, func(i, j int) bool {
return tasks[i].Priority < tasks[j].Priority
})
fmt.Println("稳定:", tasks)
}
运行结果:
不稳定:[{Task2 1} {Task4 1} {Task3 2} {Task1 2}]
稳定:[{Task2 1} {Task4 1} {Task1 2} {Task3 2}]
示例 6:降序排序
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
// 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
fmt.Println("降序:", nums) // [5 4 3 2 1]
}
示例 7:二分查找
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{1, 3, 5, 7, 9}
// 查找元素
idx := sort.SearchInts(nums, 5)
fmt.Printf("5 在索引 %d\n", idx)
// 查找不存在的元素
idx = sort.SearchInts(nums, 6)
fmt.Printf("6 应插入索引 %d\n", idx)
// 使用 Search 函数
idx = sort.Search(len(nums), func(i int) bool {
return nums[i] >= 7
})
fmt.Printf("第一个 >= 7 的索引是 %d\n", idx)
}
运行结果:
5 在索引 2
6 应插入索引 3
第一个 >= 7 的索引是 3
示例 8:检查是否已排序
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func main() {
people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
people2 := []Person{{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}}
fmt.Println("people1 已排序:", sort.SliceIsSorted(people1, func(i, j int) bool {
return people1[i].Age < people1[j].Age
}))
fmt.Println("people2 已排序:", sort.SliceIsSorted(people2, func(i, j int) bool {
return people2[i].Age < people2[j].Age
}))
}
运行结果:
people1 已排序:true
people2 已排序:false
最佳实践
1. 优先使用便捷函数
// ✅ 推荐:使用便捷函数
sort.Ints(nums)
sort.Strings(names)
// ❌ 不推荐:手动实现 Interface
sort.Sort(sort.IntSlice(nums))
2. 使用 Slice 函数简化代码
// ✅ 推荐:使用 Slice
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
// ❌ 不推荐:实现完整 Interface(除非需要复用)
type ByAge []Person
func (a ByAge) Len() int { ... }
func (a ByAge) Less(i, j int) bool { ... }
func (a ByAge) Swap(i, j int) { ... }
3. 需要保持顺序时使用稳定排序
// ✅ 需要保持相等元素原始顺序
sort.SliceStable(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
// ❌ 不关心顺序时使用普通排序(性能更好)
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
4. 降序排序使用 Reverse
// ✅ 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
// 或者使用 Slice
sort.Slice(nums, func(i, j int) bool {
return nums[i] > nums[j]
})
5. 多字段排序使用链式比较
// ✅ 多字段排序
sort.Slice(people, func(i, j int) bool {
if people[i].Name != people[j].Name {
return people[i].Name < people[j].Name
}
return people[i].Age < people[j].Age
})
与其他包配合
与 slices 包配合
package main
import (
"fmt"
"slices"
"sort"
)
func main() {
nums := []int{5, 2, 8, 1, 9}
// 使用 slices 包(Go 1.21+)
slices.Sort(nums)
fmt.Println("slices:", nums)
// 使用 sort 包
sort.Ints(nums)
fmt.Println("sort:", nums)
// 检查是否已排序
fmt.Println("IsSorted:", slices.IsSorted(nums))
fmt.Println("AreSorted:", sort.IntsAreSorted(nums))
}
使用 cmp 包进行比较
package main
import (
"cmp"
"fmt"
"sort"
)
type Item struct {
Name string
Value int
}
func main() {
items := []Item{
{"Apple", 5},
{"Banana", 3},
{"Cherry", 8},
}
// 使用 cmp.Compare
sort.Slice(items, func(i, j int) bool {
return cmp.Compare(items[i].Value, items[j].Value) < 0
})
fmt.Println(items)
}
注意事项
限制
-
排序稳定性:
Sort、Slice是不稳定排序Stable、SliceStable是稳定排序
-
性能考虑:
- 时间复杂度:O(n log n)
- 空间复杂度:O(log n)(递归栈)
-
NaN 处理:
- Float64Slice 将 NaN 排在最后
-
原地排序:
- 所有排序函数都会修改原切片
使用建议
-
确保比较函数正确:
// ❌ 错误:使用 <= 会导致 panic sort.Slice(nums, func(i, j int) bool { return nums[i] <= nums[j] // 错误! }) // ✅ 正确:使用 < sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] // 正确 }) -
检查切片是否为空:
if len(nums) <= 1 { return // 无需排序 } sort.Ints(nums) -
理解稳定性需求:
// 如果需要保持相等元素的原始顺序 sort.SliceStable(items, less) // 如果不需要,使用更快的不稳定排序 sort.Slice(items, less)
快速参考
函数速查表
| 函数 | 功能 | 稳定性 |
|---|---|---|
Find | 二分查找 | - |
Float64s | 排序 float64 切片 | 不稳定 |
Float64sAreSorted | 检查 float64 切片 | - |
Ints | 排序 int 切片 | 不稳定 |
IntsAreSorted | 检查 int 切片 | - |
IsSorted | 检查 Interface | - |
Reverse | 反转排序顺序 | - |
Search | 二分查找 | - |
SearchFloat64s | 查找 float64 | - |
SearchInts | 查找 int | - |
SearchStrings | 查找 string | - |
Slice | 使用函数排序 | 不稳定 |
SliceIsSorted | 使用函数检查 | - |
SliceStable | 稳定排序 | 稳定 |
Sort | 排序 Interface | 不稳定 |
Stable | 稳定排序 Interface | 稳定 |
Strings | 排序 string 切片 | 不稳定 |
StringsAreSorted | 检查 string 切片 | - |
类型速查表
| 类型 | 描述 | 方法 |
|---|---|---|
Interface | 排序接口 | Len, Less, Swap |
IntSlice | int 切片类型 | Len, Less, Swap, Sort, Search |
Float64Slice | float64 切片类型 | Len, Less, Swap, Sort, Search |
StringSlice | string 切片类型 | Len, Less, Swap, Sort, Search |
常见模式
// 1. 基本类型排序
sort.Ints(nums)
sort.Float64s(floats)
sort.Strings(names)
// 2. 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
// 3. 自定义类型排序
sort.Slice(items, func(i, j int) bool {
return items[i].Value < items[j].Value
})
// 4. 稳定排序
sort.SliceStable(items, func(i, j int) bool {
return items[i].Value < items[j].Value
})
// 5. 二分查找
idx := sort.SearchInts(sortedNums, target)
// 6. 检查是否已排序
if sort.IntsAreSorted(nums) {
// ...
}
// 7. 多字段排序
sort.Slice(people, func(i, j int) bool {
if people[i].Name != people[j].Name {
return people[i].Name < people[j].Name
}
return people[i].Age < people[j].Age
})
比较函数要求
// Less 函数必须满足:
// 1. 反对称性:Less(i, j) 和 Less(j, i) 不能同时为 true
// 2. 传递性:如果 Less(i, j) 和 Less(j, k) 为 true,则 Less(i, k) 必须为 true
// 3. 使用 < 而不是 <=
// ✅ 正确
func Less(i, j int) bool {
return data[i] < data[j]
}
// ❌ 错误:使用 <= 会导致 panic
func Less(i, j int) bool {
return data[i] <= data[j]
}
总结
sort 包是 Go 标准库中用于排序的核心包,提供了丰富的排序功能。
核心优势:
- ✅ 支持任意类型排序(通过 Interface)
- ✅ 提供便捷函数(Ints、Float64s、Strings)
- ✅ 支持稳定和不稳定排序
- ✅ 提供二分查找功能
- ✅ 性能优秀(O(n log n))
重要限制:
- ⚠️ Sort 和 Slice 是不稳定排序
- ⚠️ 所有排序都是原地排序
- ⚠️ 比较函数必须使用 < 而不是 <=
主要用途:
- 基本类型切片排序
- 自定义类型排序
- 使用比较函数排序
- 检查切片是否已排序
- 二分查找
使用建议:
- 优先使用便捷函数
- 使用 Slice 函数简化代码
- 需要保持顺序时使用稳定排序
- 确保比较函数正确(使用 <)
- 理解稳定性和性能权衡
Go 1.21+ 替代方案:
- 考虑使用
slices包(基于泛型) slices.Sort、slices.SortFunc等