sort
阅读提示
- 适用版本:Go 1.21+(示例在 Go 1.22 下验证)· 前置知识:语法基础-切片 · 阅读时长:约 10 分钟
TIP
如果你是 1.21 版本以上的开发者,我建议使用slices标准库来进行排序,它支持泛型,API 设计更加合理。
在 go 中的sort包下提供了官方实现的排序方法,大部分可以直接开箱即用。倘若想要对结构体进行排序的话必须实现sort.Interface下的三个方法Len() swap() Less()。由于官方已经帮我们实现了Float64Slice StringSlice IntSlice三个类型,所以这三个类型可以不用我们自己实现直接使用即可。
go
type Interface interface {
// 长度方法
Len() int
// 比较方法
Less(i, j int) bool
// 交换方法
Swap(i, j int)
}整型排序
go
func main() {
ints := []int{1, 2, 3, 111, 5, 99, 23, 5, 66}
sort.Ints(ints)
}浮点排序
go
func main() {
floats := []float64{1.0, 2.5, 3.8, 1.11, 5.5, 99.99999, 23.9999, 5.66, 66}
sort.Float64s(floats)
fmt.Println(floats)
}字符串排序
go
func main() {
strings := []string{"helloworld", "aaa", "bbb", "ccc"}
sort.Strings(strings)
}逆向排序
需要先进行sort.Reverse包装再进行排序
go
func main() {
floats := []float64{1.0, 2.5, 3.8, 1.11, 5.5, 99.99999, 23.9999, 5.66, 66}
sort.Sort(sort.Reverse(sort.Float64Slice(floats)))
fmt.Println(floats)
}自定义排序
如果想要自定义结构体排序的话,就必须实现三个方法。
go
type Person struct {
UserId string
Username string
Age int
Address string
}
type PersonSlice []Person
//返回切片的长度
func (p PersonSlice) Len() int {
return len(p)
}
//比较方法
func (p PersonSlice) Less(i, j int) bool {
return p[i].Age < p[j].Age
}
//交换方法
func (p PersonSlice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}由于是根据年龄比较的,所有结果是根据年龄的大小来排序。
go
func main() {
persons := []Person{{
UserId: "1",
Username: "wyh",
Age: 18,
Address: "us",
}, {
UserId: "2",
Username: "jack",
Age: 17,
Address: "ch",
}, {
UserId: "3",
Username: "mike",
Age: 15,
Address: "india",
}}
sort.Sort(PersonSlice(persons))
fmt.Println(persons)
}是否有序
判断一个切片是否有序,其内部并不会进行排序操作,而是通过循环调用Less()来判断
go
func main() {
persons := []Person{{
UserId: "1",
Username: "wyh",
Age: 18,
Address: "us",
}, {
UserId: "2",
Username: "jack",
Age: 17,
Address: "ch",
}, {
UserId: "3",
Username: "mike",
Age: 15,
Address: "india",
}}
sort.Sort(PersonSlice(persons))
println(sort.IsSorted(PersonSlice(persons)))
}完整示例
下面的程序可以直接运行:复制到文件后执行 go run main.go,或粘贴到 Go Playground 运行。
go
package main
import (
"fmt"
"sort"
)
type User struct {
Name string
Age int
}
func main() {
users := []User{{"Bob", 30}, {"Alice", 25}, {"Carol", 30}}
sort.SliceStable(users, func(i, j int) bool { return users[i].Age < users[j].Age })
fmt.Println(users)
nums := []int{3, 1, 2}
sort.Ints(nums)
fmt.Println(nums, sort.SearchInts(nums, 2))
}预期输出:
text
[{Alice 25} {Bob 30} {Carol 30}]
[1 2 3] 1常见错误与踩坑
sort.Slice不稳定。 相等元素可能被交换;需要保持原顺序时用sort.SliceStable。- 比较函数必须是严格弱序。 写成
<=而不是<会导致未定义结果。 sort.Search*系列要求数据已排序。 在无序切片上搜索会静默返回错误结果。Less要尽量轻量。 它会被调用 O(n log n) 次,昂贵计算应提前算好。- 优先用现成辅助函数。
sort.Ints、sort.Strings、sort.SliceStable已覆盖大多数场景。
更新记录
- 2026-10-14:新增"阅读提示"、完整可运行示例(含预期输出)、常见错误与踩坑清单,以及本更新记录。
