Go sort.Interface的基本使用

 更新时间:2026年04月13日 09:46:22   作者: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语言中乐观锁与悲观锁的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Go语言包管理模式示例分析

    Go语言包管理模式示例分析

    这篇文章主要为大家介绍了Go语言包管理模式示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 一文详解Golang连接kafka的基本操作

    一文详解Golang连接kafka的基本操作

    这篇文章主要为大家详细介绍了Golang中连接kafka的基本操作的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-03-03
  • Go语言实现并发控制的常见方式详解

    Go语言实现并发控制的常见方式详解

    这篇文章主要为大家详细介绍了Go语言实现并发控制的几种常见方式,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2024-03-03
  • Golang Map value不可寻址使用指针类型代替示例详解

    Golang Map value不可寻址使用指针类型代替示例详解

    这篇文章主要为大家介绍了Golang Map value不可寻址使用指针类型代替示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Go语言通道之缓冲通道

    Go语言通道之缓冲通道

    这篇文章介绍了Go语言通道之缓冲通道,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • golang实现java uuid的序列化方法

    golang实现java uuid的序列化方法

    这篇文章主要介绍了golang实现java uuid的序列化方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 详解GO语言中[]byte与string的两种转换方式和底层实现

    详解GO语言中[]byte与string的两种转换方式和底层实现

    这篇文章主要为大家详细介绍了GO语言中[]byte与string的两种转换方式和底层实现的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以参考下
    2024-03-03
  • golang 原生database\sql 的重连机制实现

    golang 原生database\sql 的重连机制实现

    本文主要介绍了golang 原生database\sql 的重连机制实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • Go切片扩容机制详细说明和举例

    Go切片扩容机制详细说明和举例

    Go 语言中的切片是一种动态数组,它可以自动扩容和缩容以适应不同的数据量,这篇文章主要给大家介绍了关于Go切片扩容机制详细说明和举例的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03

最新评论