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语言学习之映射(map)的用法详解

    Go语言学习之映射(map)的用法详解

    Map是一种无序的键值对的集合。这篇文章主要为大家详细介绍了Go语言中映射的用法,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
    2022-04-04
  • Go处理包含多种引号的字符串的几种方法

    Go处理包含多种引号的字符串的几种方法

    在Go中,有几种方式可以处理包含多种引号的字符串,以确保代码的可读性和正确性,本文将给大家详细介绍了这几种处理方式,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-04-04
  • Go 代码块作用域变量遮蔽问题解析

    Go 代码块作用域变量遮蔽问题解析

    这篇文章主要为大家介绍了Go 代码块作用域变量遮蔽问题解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 详解如何使用Golang操作MongoDB数据库

    详解如何使用Golang操作MongoDB数据库

    在现代开发中,数据存储是一个至关重要的环节,MongoDB作为一种NoSQL数据库,提供了强大的功能和灵活的数据模型,与Golang的高性能和并发性能非常契合,本文将探讨Golang与MongoDB的完美组合,介绍如何使用Golang操作MongoDB数据库,需要的朋友可以参考下
    2023-11-11
  • golang 接口嵌套实现复用的操作

    golang 接口嵌套实现复用的操作

    这篇文章主要介绍了golang 接口嵌套实现复用的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go接口构建可扩展Go应用示例详解

    Go接口构建可扩展Go应用示例详解

    本文深入探讨了Go语言中接口的概念和实际应用场景。从基础知识如接口的定义和实现,到更复杂的实战应用如解耦与抽象、多态、错误处理、插件架构以及资源管理,文章通过丰富的代码示例和详细的解释,展示了Go接口在软件开发中的强大功能和灵活性
    2023-10-10
  • Go语言Http Server框架实现一个简单的httpServer

    Go语言Http Server框架实现一个简单的httpServer

    这篇文章主要为大家介绍了Go语言Http Server框架实现一个简单的httpServer抽象,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • golang方法中receiver为指针与不为指针的区别详析

    golang方法中receiver为指针与不为指针的区别详析

    这篇文章主要给大家介绍了关于golang方法中receiver为指针与不为指针区别的相关资料,其实最大的区别应该是指针传递的是对像的引用,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • 服务器端Go程序对长短链接的处理及运行参数的保存

    服务器端Go程序对长短链接的处理及运行参数的保存

    这篇文章主要介绍了服务器端Go程序对长短链接的处理及运行参数的保存,这里针对使用Go语言编写的Socket服务器进行实例说明,需要的朋友可以参考下
    2016-03-03
  • Go语言防范SQL注入CSRF及XSS攻击实例探究

    Go语言防范SQL注入CSRF及XSS攻击实例探究

    在本文中,我们将会介绍几种最常见的攻击类型,并且介绍如何使用Golang来防范这些攻击,本文会涉及XSS攻击、CSRF攻击、SQL注入等,如果你想学习Golang和网络安全的相关知识,那么这篇文章会是一个很好的开始
    2024-01-01

最新评论