Go?sort.Interface的基本使用
sort.Interface
Go 語言的 sort.Sort 函數(shù)不會對具體的序列和它的元素做任何假設(shè)。它使用了一個接口類型 sort.Interface 來指定通用的排序算法和可能被排序到的序列類型之間的約定。
一個內(nèi)置的排序算法需要知道三個東西:序列的長度,表示兩個元素比較的結(jié)果,一種交換兩個元素的方式; 這就是 sort.Interface 的三個方法:
package sort
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}為了對序列進(jìn)行排序,我們需要定義一個實現(xiàn)了這三個方法的類型,然后對這個類型的一個實例應(yīng)用 sort.Sort 函數(shù)。
思考對一個字符串切片進(jìn)行排序,這可能是最簡單的例子了。下面是實現(xiàn)了一個新的類型 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]
}現(xiàn)在我們可以通過像下面這樣將一個切片轉(zhuǎn)換為一個 StringSlice類型來進(jìn)行排序:
sort.Sort(StringSlice(s))
上述 Less 方法中 " < " 代表按升序排序。
基礎(chǔ)類型的切片排序
對字符串切片的排序是很常用的需要,所以 sort 包直接提供了 StringSlice 類型:
s := []string{"a", "c", "b"}
sort.Sort(sort.StringSlice(s))也提供了 Strings 函數(shù)能讓上面這些調(diào)用簡化成:
s := []string{"a", "c", "b"}
sort.Strings(s)總結(jié)一下,對于 []int, []float64, []string 這種元素類型是基礎(chǔ)類型的切片,使用 sort 包提供的下面幾個函數(shù)進(jìn)行排序。
sort.Ints sort.Floats sort.Strings
結(jié)構(gòu)體元素類型切片排序
現(xiàn)在有一個元素類型為 Person 結(jié)構(gòu)體的切片,結(jié)構(gòu)體對象有 Name,Score,Age 字段,現(xiàn)按照 Name 進(jìn)行排序:
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 進(jìn)一步簡化,該函數(shù)默認(rèn)實現(xiàn)了排序所需要的 Len 和 Swap 方法,傳入排序?qū)ο蠛?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}]任意數(shù)據(jù)結(jié)構(gòu)排序
實現(xiàn)了 sort.Interface 的具體類型不一定是切片類型,下面為PersonSort 結(jié)構(gòu)體類型實現(xiàn)排序接口:
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}]
}到此這篇關(guān)于Go sort.Interface的基本使用的文章就介紹到這了,更多相關(guān)Go sort.Interface內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang高并發(fā)限流操作 ping / telnet
這篇文章主要介紹了golang高并發(fā)限流操作 ping / telnet,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
使用Go語言快速構(gòu)建靜態(tài)資源服務(wù)
在?Web?開發(fā)中,除了提供?API?接口外,往往還需要對外提供靜態(tài)資源服務(wù),比如:CSS,JS,圖片等,本文將用?Gin?框架?演示如何快速構(gòu)建一個靜態(tài)資源服務(wù),希望對大家有所幫助2025-08-08
Golang?pprof監(jiān)控之cpu占用率統(tǒng)計原理詳解
經(jīng)過前面的幾節(jié)對pprof的介紹,對pprof統(tǒng)計的原理算是掌握了七八十了,但唯獨(dú)還沒有分析pprof?工具是如何統(tǒng)計cpu使用情況的,今天我們來分析下這部分2023-04-04
go語言使用range來接收通道里面的數(shù)據(jù)
本文主要介紹了go語言使用range來接收通道里面的數(shù)據(jù),for ... range?循環(huán)會一直從通道中接收值,直到通道關(guān)閉并且所有值都被接收完畢,下面就來介紹一下,感興趣的可以了解一下2025-04-04
Golang微服務(wù)框架Kratos實現(xiàn)Kafka消息隊列的方法
消息隊列是大型分布式系統(tǒng)不可缺少的中間件,也是高并發(fā)系統(tǒng)的基石中間件,所以掌握好消息隊列MQ就變得極其重要,在本文當(dāng)中,您將了解到:什么是消息隊列?什么是Kafka?怎樣在微服務(wù)框架Kratos當(dāng)中應(yīng)用Kafka進(jìn)行業(yè)務(wù)開發(fā),需要的朋友可以參考下2023-09-09
Golang中make與new使用區(qū)別小結(jié)
Go語言中new和make是內(nèi)建的兩個函數(shù),主要用來創(chuàng)建分配類型內(nèi)存,本文主要給大家介紹了Go語言中函數(shù)new與make的使用和區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-01-01

