Go sort.Interface的基本使用

 更新时间:2026年04月14日 08:57:50   作者:Go_error  
本文主要介绍了Go sort.Interface的基本使用,及对不同类型的数据进行排序,包括字符串切片、结构体切片等,并提供了具体示例,具有一定的参考价值,感兴趣的可以了解一下

sort.Interface

Go 语言的 sort.Sort 函数不会对具体的序列和它的元素做任何假设。它使用了一个接口类型 sort.Interface 来指定通用的排序算法和可能被排序到的序列类型之间的约定。

一个内置的排序算法需要知道三个东西:序列的长度,表示两个元素比较的结果,一种交换两个元素的方式; 这就是 sort.Interface 的三个方法:

package sort
type Interface interface {
 Len() int
 Less(i, j int) bool
 Swap(i, j int)
}

为了对序列进行排序,我们需要定义一个实现了这三个方法的类型,然后对这个类型的一个实例应用 sort.Sort 函数。

思考对一个字符串切片进行排序,这可能是最简单的例子了。下面是实现了一个新的类型 StringSlice 和它的 Len,Less 和 Swap 方法:

type StringSlice []string
func (x StringSlice) Len() int           { return len(x) }
func (x StringSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x StringSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func main() {
 s := []string{"a", "c", "b"}
 sort.Sort(StringSlice(s))
 fmt.Println(s) // [a b c]
}

现在我们可以通过像下面这样将一个切片转换为一个 StringSlice类型来进行排序:

 sort.Sort(StringSlice(s))

上述 Less 方法中 " < " 代表按升序排序。

基础类型的切片排序

对字符串切片的排序是很常用的需要,所以 sort 包直接提供了 StringSlice 类型:

 s := []string{"a", "c", "b"}
 sort.Sort(sort.StringSlice(s))

也提供了 Strings 函数能让上面这些调用简化成:

 s := []string{"a", "c", "b"}
 sort.Strings(s)

总结一下,对于 []int, []float64, []string 这种元素类型是基础类型的切片,使用 sort 包提供的下面几个函数进行排序。

sort.Ints
sort.Floats
sort.Strings

结构体元素类型切片排序

现在有一个元素类型为 Person 结构体的切片,结构体对象有 Name,Score,Age 字段,现按照 Name 进行排序:

type Person struct {
 Name  string
 Score int
 Age   int
}
type Persons []Person
func (p Persons) Len() int           { return len(p) }
func (p Persons) Less(i, j int) bool { return p[i].Name < p[j].Name }
func (p Persons) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func main() {
 p := Persons{
  {"c", 90, 30},
  {"b", 100, 10},
  {"c", 90, 20},
 }
 sort.Sort(p)
 fmt.Println(p) // [{b 100 10} {c 90 30} {c 90 20}]
}

新增需求如果 Name 相同,按 Score 排序,Score 相同,按 Age 排序,修改 Less 方法:

type Person struct {
 Name  string
 Score int
 Age   int
}
type Persons []Person
func (p Persons) Len() int { return len(p) }
func (p Persons) Less(i, j int) bool {
 if p[i].Name != p[j].Name {
  return p[i].Name < p[j].Name
 }
 if p[i].Score != p[j].Score {
  return p[i].Score < p[j].Score
 }
 return p[i].Age < p[j].Age
}
func (p Persons) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func main() {
 p := Persons{
  {"c", 90, 30},
  {"b", 100, 10},
  {"c", 90, 20},
 }
 sort.Sort(p)
 fmt.Println(p) // [{b 100 10} {c 90 20} {c 90 30}]
}

可以使用 sort.Slice 进一步简化,该函数默认实现了排序所需要的 Len 和 Swap 方法,传入排序对象和 Less 方法即可:

 p := Persons{
  {"c", 90, 30},
  {"b", 100, 10},
  {"c", 90, 20},
 }
 sort.Slice(p, func(i, j int) bool {
  if p[i].Name != p[j].Name {
   return p[i].Name < p[j].Name
  }
  if p[i].Score != p[j].Score {
   return p[i].Score < p[j].Score
  }
  return p[i].Age < p[j].Age
 })
 fmt.Println(p) // [{b 100 10} {c 90 20} {c 90 30}]

任意数据结构排序

实现了 sort.Interface 的具体类型不一定是切片类型,下面为PersonSort 结构体类型实现排序接口:

type Person struct {
 Name  string
 Score int
 Age   int
}
type PersonSort struct {
 p    []Person
 less func(i, j Person) bool
}
func (p PersonSort) Len() int { return len(p.p) }
func (p PersonSort) Less(i, j int) bool { return p.less(p.p[i], p.p[j]) }
func (p PersonSort) Swap(i, j int) { p.p[i], p.p[j] = p.p[j], p.p[i] }
func main() {
 p := []Person{
  {"c", 90, 30},
  {"b", 100, 10},
  {"c", 90, 20},
 }
 less := func(i, j Person) bool {
  if i.Name != j.Name {
   return i.Name < j.Name
  }
  if i.Score != j.Score {
   return i.Score < j.Score
  }
  return i.Age < j.Age
 }
 sort.Sort(PersonSort{p, less})
 fmt.Println(p) // [{b 100 10} {c 90 20} {c 90 30}]
}

到此这篇关于Go sort.Interface的基本使用的文章就介绍到这了,更多相关Go sort.Interface内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Go语言中的数据库操作

    详解Go语言中的数据库操作

    数据库是应用开发中必须要掌握的技巧。这篇文章主要和大家介绍一下Go语言中相关的数据库操作,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-02-02
  • 浅析Golang中Gin框架存在的必要性

    浅析Golang中Gin框架存在的必要性

    在Go语言中,net/http 包提供了一个强大且灵活的标准HTTP库,那为什么还出现了像 Gin 这样的,方便我们构建Web应用程序的第三方库,下面就来和大家简单分析一下
    2023-08-08
  • golang高并发限流操作 ping / telnet

    golang高并发限流操作 ping / telnet

    这篇文章主要介绍了golang高并发限流操作 ping / telnet,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 使用Go语言快速构建静态资源服务

    使用Go语言快速构建静态资源服务

    在 Web 开发中,除了提供 API 接口外,往往还需要对外提供静态资源服务,比如:CSS,JS,图片等,本文将用 Gin 框架 演示如何快速构建一个静态资源服务,希望对大家有所帮助
    2025-08-08
  • Golang pprof监控之cpu占用率统计原理详解

    Golang pprof监控之cpu占用率统计原理详解

    经过前面的几节对pprof的介绍,对pprof统计的原理算是掌握了七八十了,但唯独还没有分析pprof 工具是如何统计cpu使用情况的,今天我们来分析下这部分
    2023-04-04
  • go语言使用range来接收通道里面的数据

    go语言使用range来接收通道里面的数据

    本文主要介绍了go语言使用range来接收通道里面的数据,for ... range 循环会一直从通道中接收值,直到通道关闭并且所有值都被接收完毕,下面就来介绍一下,感兴趣的可以了解一下
    2025-04-04
  • Golang微服务框架Kratos实现Kafka消息队列的方法

    Golang微服务框架Kratos实现Kafka消息队列的方法

    消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件,所以掌握好消息队列MQ就变得极其重要,在本文当中,您将了解到:什么是消息队列?什么是Kafka?怎样在微服务框架Kratos当中应用Kafka进行业务开发,需要的朋友可以参考下
    2023-09-09
  • Go语言开发快速学习CGO编程

    Go语言开发快速学习CGO编程

    这篇文章主要为大家介绍了Go语言开发之快速学习CGO编程,看了本文你就会发现CGO编程其实没有想象的那么难,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Golang中make与new使用区别小结

    Golang中make与new使用区别小结

    Go语言中new和make是内建的两个函数,主要用来创建分配类型内存,本文主要给大家介绍了Go语言中函数new与make的使用和区别,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • golang开启mod后import报红的简单解决方案

    golang开启mod后import报红的简单解决方案

    这篇文章主要给大家介绍了关于golang开启mod后import报红的简单解决方案,文中通过图文将解决的办法介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01

最新评论