Go 里面在使用结构体切片时,往往我们插入值的顺序,不一定就是我们要使用时的顺序。

这时就需要进行按某个条件进行排序。

map 类型也同样会遇到这么一个问题,那怎么快速对他们进行排序呢?

我们先从 map 类型入手。

一个无序的 map

先来看一段代码:

1
2
3
4
5
6
7
8
9
type User map[string]string

func (this User) String() string {
	rst := ""
	for k, v := range this {
		rst += fmt.Sprintf("%v=%v \n", k, v)
	}
	return rst
}

我这里声明了一个 user 的 map,同时实现了 String 方法,这个方法会在 fmt 打印他时被调用。

然后我们在 main 方法里面去初始化打印下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
	m := User{
		"id":   "23",
		"name": "张三",
		"age":  "12",
		"set":  "1",
	}
	fmt.Println(m)
}

// 执行第一次结果
name=张三
age=12
set=1
id=23

// 执行第二次结果
set=1
id=23
name=张三
age=12

如果没有出现不一样的结果,你就多执行几次,一般 3-4 四次就很大可能出现不一样的排序。

使用 sort 包对他进行排序

sort 是我们的 go 官方的基础包,是专门用来处理排序的;

它提供了一个方法 sort.Sort 这个方法,我只需要将我们的实例,传入进去就能排序好;

但是传入的实例,必须实现一个接口:

1
2
3
4
5
type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
}

也就是上面的这三个方法,即可完成排序。

接下来我们使用官方的 sort 包对他进行排序:

1
2
3
4
5
6
7
8
func (this User) Keys() []string {
	keys := make([]string, 0)
	for k, _ := range this {
		keys = append(keys, k)
	}
	sort.Sort(sort.StringSlice(keys))
	return keys
}

我们的思路是,先把所有的 key 取出来进行排序,然后再根据这个排序好的 key 进行取值排序输出。

这里我们用到了 sort.StringSlice 方法,这是将我们的字符串数组,转换成实现了那个接口的实例!

现在我们再打印输出就能看到结果是这样的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
m := User{
	"id":   "23",
	"name": "张三",
	"age":  "12",
	"set":  "1",
}

fmt.Println(m.Keys())

// 输出结果
[age id name set]

这回你怎么反复的执行都是一样的结果,首字母都是 a-z 的排序。

扩展到结构体

如果是对字符串数组,可以直接 sort.StringSlice 方法转换,如果是结构体,就得我们自己手动去实现那接口了。

首先我们先来创建一个我们自定义的结构体:

1
2
3
4
5
type User struct {
	Name string
	Age  int
	Sex  int
}

此时我们去实现一个没有排序的数组:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func main() {
	users := []User{
		{
			Name: "张三",
			Age:  10,
			Sex:  0,
		},
		{
			Name: "李四",
			Age:  40,
			Sex:  0,
		},
		{
			Name: "王五",
			Age:  20,
			Sex:  1,
		},
	}
	fmt.Println(users)
}

// 输出结果
[{张三 10 0} {李四 40 0} {王五 20 1}]

注意 age 这个值,现在是怎么初始化就是怎么样的,10,40,20 的排序。

现在我就需要去做排序工作了,首先我们需要去定义一个 user 切片类型的类型,方便进行扩展,实现 sort 的排序方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type Users []User

func (this Users) Len() int {
	return len(this)
}

func (this Users) Less(i, j int) bool {
	//根据年龄大小
	return this[i].Age < this[j].Age
}

func (this Users) Swap(i, j int) {
	this[i], this[j] = this[j], this[i]
}

像上面的这样就好了,感觉应该不需要做过多讲解吧,应该都能看懂,如果有疑问,欢迎到我们交流群提问!

接下来我们只需要在需要排序时,调下 sort.Sort 就可以排序好了。

上代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func main() {

	users := ...//这里和上面一样的初始化

	sort.Sort(Users(users))
	fmt.Println(users)
}

//输出结果
[{张三 10 0} {王五 20 1} {李四 40 0}]

最后的结果就是按照我们设定的排序规则排序的。