Standard library patterns · 3 MIN READ
Sorting by whatever you like
Sort a slice of structs by two keys.
slices.SortFunc takes a comparison that returns a negative number, zero or a positive one — not a bool. That trips people coming from languages where the comparator answers "is a before b". cmp.Compare does the right thing for any ordered type and is what the comparison should usually be built from.
For a second key, compare the first and fall through only when it is equal. That is the whole pattern, and it is worth writing out once.
SEE THE IDEA
Compare the first key, then break ties with the second
- 01
Primary key
gocmp.Compare(a.Year, b.Year)Negative, zero or positive
- 02
Equal primary
goif result == 0Only now compare another key
- 03
Secondary key
gocmp.Compare(a.Name, b.Name)Produces the final ordering
slices.SortFunc takes a three-way comparison, not a less-than boolean.
In practice
Make the comparison consistent and transitive so the sorting algorithm can rely on it. Sorting changes the supplied slice in place; clone first if callers need the original order. Use SortStableFunc when equal elements must retain their original relative order.
Watch out
Subtracting integers as a comparator can overflow. cmp.Compare expresses the ordering without that overflow risk.
Work through the exercise
package main
type Release struct {
Name string
Year int
}
// SortReleases orders by year ascending, and by name for
// releases from the same year. It sorts in place.
func SortReleases(releases []Release) {}
func main() {}Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.
Progress stays in this browser. No account needed.