Sorting
Sorting in Go got dramatically nicer in Go 1.21, when the generic slices
package landed. For anything naturally ordered — numbers, strings — it's one
call:
package main
import (
"fmt"
"slices"
)
func main() {
nums := []int{3, 1, 4, 1, 5}
slices.Sort(nums)
fmt.Println(nums) // [1 1 3 4 5]
words := []string{"cherry", "apple", "banana"}
slices.Sort(words)
fmt.Println(words) // [apple banana cherry]
}
Note that slices.Sort sorts in place: it rearranges the slice you hand
it and returns nothing. If the caller still needs the original order, copy
first — slices.Clone(nums) gives you an independent copy to sort.
Custom orderings with SortFunc
Structs have no built-in order — is a Person "less than" another by name,
or by age? You decide, by passing a comparison function to
slices.SortFunc. The function returns a negative number when a should
sort before b, positive when after, and 0 when they're equal:
package main
import (
"cmp"
"fmt"
"slices"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{{"Carol", 30}, {"Alice", 25}, {"Bob", 30}}
slices.SortFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println(people) // [{Alice 25} {Carol 30} {Bob 30}]
}
cmp.Compare(a, b) from the cmp package does the negative/zero/positive
dance for you on any ordered type — much cleaner than writing the if
ladder by hand.
Tie-breaking
Carol and Bob are both 30 — which comes first? With the comparison above, it's unspecified. To break ties, compare the next field when the first comparison returns 0:
slices.SortFunc(people, func(a, b Person) int {
if c := cmp.Compare(a.Age, b.Age); c != 0 {
return c
}
return cmp.Compare(a.Name, b.Name) // tie-break by name
})
Read it as "order by age, then by name" — the same idea as SQL's
ORDER BY age, name. Chain as many fields as you need.
Related, in one sentence: slices.SortStableFunc is the variant that keeps
equal elements in their original relative order, which matters when you
sort an already-meaningfully-ordered slice by a second criterion.
The older way: sort.Slice
Code written before Go 1.21 uses the sort package instead — you'll see
sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age }) all over existing codebases. It works fine, but it
compares by index and isn't type-checked as tightly. For new code, prefer
slices.SortFunc.
Descending order
No separate function needed — just flip the arguments:
cmp.Compare(b.Age, a.Age) sorts oldest first.
Your turn
The exercise asks you to sort people by age ascending, ties broken by name —
exactly the two-level comparison above. One twist: the function must
return a new sorted slice and leave its input untouched. Since
slices.SortFunc sorts in place, that means cloning before sorting. The
hidden test checks the original slice afterward, so a sneaky in-place sort
will be caught.
Practice
1. Sort People
IntermediateImplement
sortPeople, which returns a new slice sorted by age ascending, with ties broken by name ascending:type Person struct { Name string Age int } func sortPeople(people []Person) []Person- Sort by
Ageascending; when two people share an age, the one whoseNamesorts first alphabetically comes first. - Do not mutate the input. The caller's slice must be in its original
order after the call — copy it first (
slices.Cloneis your friend), then sort the copy. - An empty or nil input returns an empty (or nil) slice.
Example:
in := []Person{{"Carol", 30}, {"Alice", 25}, {"Bob", 30}} out := sortPeople(in) // out: [{Alice 25} {Bob 30} {Carol 30}] // in is still: [{Carol 30} {Alice 25} {Bob 30}]package main import "fmt" // Person is one entry in a directory of people. type Person struct { Name string Age int } // sortPeople returns a new slice sorted by Age ascending, ties broken by // Name ascending. It must not modify the input slice. func sortPeople(people []Person) []Person { // TODO: implement return nil } func main() { in := []Person{{"Carol", 30}, {"Alice", 25}, {"Bob", 30}} fmt.Println(sortPeople(in)) fmt.Println(in) // must be unchanged }Sign in to write and run your solution in the browser.
Sign in for hints and the solution.
- Sort by