在go语言中, 如果要对intfloat等基本类型进行排序时,在sort包中提供了如下方法可以进行调用

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }
​
// Float64s sorts a slice of float64s in increasing order
// (not-a-number values are treated as less than other values).
func Float64s(a []float64) { Sort(Float64Slice(a)) }
​
// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

可以看到在调用这些方法后,会把参数转成Float64Slice或者IntSlice等自定义类型再用Sort进行排序。 从源码可以看到,这些自定义类型都是实现了Interface这个接口中的三种方法。

type Interface interface {
    // Len is the number of elements in the collection.
    Len() int
    // Less reports whether the element with
    // index i should sort before the element with index j.
    Less(i, j int) bool
    // Swap swaps the elements with indexes i and j.
    Swap(i, j int)
}
​
type IntSlice []int
​
func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
​
// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }
​
// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order
// (not-a-number values are treated as less than other values).
type Float64Slice []float64
​
func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

所以如果我们要实现自定义的排序规则时,可以自定义类型,然后去实现接口中的这三个方法即可。 加入需要按照学生的名字进行排序,我们可以这么写

type Students []Student
​
func (s Students) Len() int {
    return len(s)
}
​
func (s Students) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}
func (s Students) Less(i, j int) bool {
    return s[i].Name < s[j].Name
}
​
func main() {
    stus := []Student{
        {Name: "zhangsan"},
        {Name: "lisi"},
        {Name: "wangwu"},
    }
    sort.Sort(Students(stus))
    for _, val := range stus {
        fmt.Println(val)
    }
}
​
/*output
{lisi }
{wangwu }
{zhangsan }
*/

虽然上面这种方式可以实现自定义排序了,但是如果需要有多种排序规则的话,每次都需要自定义新的类型,然后重复去实现这三个方法,而实际不同的也就是Less(i,j int)bool这个方法而已。 所以sort包中还提供了另外一个方式实现排序。可以使用sort.Slice()这个方法,然后传入Less比较规则即可。

func main() {
    stus := []Student{
        {Name: "zhangsan"},
        {Name: "lisi"},
        {Name: "wangwu"},
    }
    sort.Slice(stus, func(i, j int) bool {
        return stus[i].Name < stus[j].Name
    })
    for _, val := range stus {
        fmt.Println(val)
    }
​
}

除了sort.Slice()方法外,sort.SliceStable()这个方法使用方式也一样。