在程序开发中,不可避免的需要给数据集进行排序,如果在语言级别不提供支持的话,我们则需要自己写算法进行数据的处理,麻烦还不一定高效。
幸好Golang在标准包中,官方有提供sort包中Sort()函数提供排序功能。并且天然支持[]int,[]float64,[]string切片的排序查找功能,并且也能够实现对自定义类型集合的排序。
下面我们先来看下golang中Sort函数的结构是什么样的。

func Sort(data Interface) {
	n := data.Len()
	quickSort(data, 0, n, maxDepth(n))
}

可以看到,该函数接收的唯一的参数就是待排序集合,该集合应是一个Interface,而我们如果需要让自定义类型的集合能够被排序,则需要实现该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)
}

数据集合实现了这三个方法后,就可以使用该包的Sort()函数进行排序。

1.1让我们来看一个以学生年龄排序的小案例:

type Stu []student

func main() {
	var students = make(Stu, 0)
	for i := 0; i < 10; i++ {
		stu := student{
			name: strconv.Itoa(i) + "~~",
			age:  i,
		}
		students = append(students, stu)
	}
	for _, item := range students {
		fmt.Println(item.name, "--", item.age)
	}
	sort.Sort(students)
	fmt.Println("is sorted? ", sort.IsSorted(students)) //可以检测是否已经排序
	for _, item := range students {
		fmt.Println(item.name, "--", item.age)
	}
}

func (s Stu) Len() int { //返回集合的长度
	return len(s)
}

//Less 被定义为:i 在 j前面为true;所以我们比较i < j 是否为 true,
//i < j = false,表示i放在后面,所以当前是降序
func (s Stu) Less(i, j int) bool { //用来决定是升序还是降序
	return s[i].age > s[j].age
}

func (s Stu) Swap(i, j int) { //改变数据在集合中的位置
	s[i], s[j] = s[j], s[i]
}


type student struct {
	name string
	age  int
}

在Less方法中,我使用的是int类型的年龄来进行降序排列的,如果需要升序只需要变成 < 号即可:

func (s Stu) Less(i, j int) bool {
	return s[i].age < s[j].age
}

1.2最后再来个基本int型的使用案例

在sort包中,给[]int排序的方法是IntSlice,结构如下:

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) }

可以看到,该[]int也实现了Sort函数中的接口,并且有一个Sort()方法,所以我们可以这样使用:

var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.IntSlice(nums).Sort()

如果我们不想这么麻烦,sort包为我们提供了一个Ints方法,调用该方法可以直接排序:

var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.Ints(nums)
fmt.Println(nums)

输出结果:
[1 2 3 3 3 5 65]
如果需要改变排序方式的话,包中同样有提供一个Reverse方法:

func Reverse(data Interface) Interface {
	return &reverse{data}
}

我们看到,Reverse函数跟Sort函数接收同样的方法,所以我们的排序时需要使用实现了那三个方法的IntSlice方法,使用方式:

sort.Sort(sort.Reverse(sort.IntSlice(nums)))

剧终!