1. The slice Package
If your Go package is anything newer than 1.21, and the items in the slice are of the cmp.Ordered type, you should definitely use the slice.Sort() function.
import (
"fmt"
"slice"
)
func main() {
nums := []int{4, 1, 3, 2}
slices.Sort(nums)
fmt.Println(nums) // Prints 1, 2, 3, 4
}It only works if you intend to sort it in place and in ascending order, though.
So if we want to sort something in descending order, or if the items have complex data types, we go for this approach.
Here’s the definition of the SortFunc function:
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int)cmp is a function that returns a negative value, e.g. -1 if a < b, a positive value, e.g. 1 if a > b, and 0 if a = b.
import (
"cmp"
"slices"
)
type Product struct {
Name string
Price int
}
func main() {
products := []Product{{"Book", 15}, {"Pen", 2}}
slices.SortFunc(products, func(a, b Product) int {
return cmp.Compare(a.Price, b.Price)
})
}cmp.Compare is a function from the cmp package that only accepts Ordered data types. It’s defined as:
package cmp
func Compare[T Ordered](x, y T) int {
// Details omitted
}Instead of using that cmp.Compare function, we can write our own comparator too:
slices.SortFunc(products, func(a, b Product) int {
if a.Price < b.Price {
return -1
} else if a.Price > b.Price {
return 1
} else {
return 0
}
})2. The Oldschool Legacy sort Package
You really shouldn’t use these unless your Go version is not yet 1.21+. These functions are very type-specific.
For example:
import "sort"
ints := []int{4, 1, 3, 2}
sort.Ints(ints) // [1, 2, 3, 4]
strings := []string{"banana", "apple"}
sort.Strings(strings) // ["apple", "banana"]It’s hard to believe we once relied on these guys.
And what if we want to customise these? We use the sort.Slice function. Here’s its definition:
func Slice(x any, less func(i, j int) bool)This time it wants us to implement a less function to determine if i is less than j, therefore sorting them in ascending order.
import "sort"
type Person struct {
Name string
Age int
}
func main() {
people := []Person{{"Alice", 25}, {"Bob", 20}}
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
}“And If you feel dorky”
With the sort package, there’s another way to customise sorting, i.e., to have your custom data type implement the sort.Interface:
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with index i
// must sort before the element with index j.
// If both Less(i, j) and Less(j, i) are false,
// then the elements at index i and j are considered equal
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}By implementing this, you get full control over the sort.