Compare sort.Slice, sort.SliceStable, sort.Sort (sort.Interface) and slices.SortFunc. Which are stable, and what are the performance differences?
Question 533MediumGo 1.22 to 1.25
Stable: sort.SliceStable, sort.Stable and slices.SortStableFunc. Not stable: sort.Slice, sort.Sort, slices.Sort and slices.SortFunc, which all use pdqsort since Go 1.19. Equal elements may be reordered.
sort.Sortmakes an interface method call for everyLessandSwap.sort.Sliceuses a reflection-based swapper plus an index-basedless(i, j)closure. The closure must reference the same slice you pass in, and getting that wrong is a classic bug.slices.SortFunc(Go 1.21+) is generic, so the compiler specializes it per type. It has no reflection and no interface dispatch, and it is usually the fastest choice. It takes a three-waycmp(a, b) inton the elements rather than on indices.slices.Sortforcmp.Orderedtypes is faster still. Since Go 1.22,sort.Intsandsort.Stringsjust callslices.Sort.
type Person struct {
Name string
Age int
}
people := []Person{{"Cy", 30}, {"Al", 25}, {"Bo", 30}}
// Age descending, then Name ascending (cmp.Or is Go 1.22+)
slices.SortFunc(people, func(a, b Person) int {
return cmp.Or(cmp.Compare(b.Age, a.Age), strings.Compare(a.Name, b.Name))
})
fmt.Println(people) // [{Bo 30} {Cy 30} {Al 25}]
// Keep the existing order among equal ages
slices.SortStableFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
What the interviewer is looking for: you pick slices in new code and you know that stability matters when you sort by several keys in successive passes. The comparator must also be a strict weak ordering. An inconsistent less gives a garbage order but does not panic.
More on More Standard Library Essentials
- Q532How do you implement a priority queue with container/heap? Why must Push and Pop use pointer receivers, and what does heap.Fix do?
- Q534How does Go's time layout work (the reference time Mon Jan 2 15:04:05 MST 2006)? What bugs come from using "2006-01-02" vs "YYYY-MM-DD", time zones and time.Parse vs time.ParseInLocation?
- Q535Compare math/rand, math/rand/v2 and crypto/rand. What changed about seeding in Go 1.20 and 1.22, and when must you use crypto/rand?
- Q536text/template vs html/template: how does contextual auto-escaping prevent XSS, and what does template.HTML bypass?
- Q537How do you prevent SQL injection with database/sql? Why can't placeholders be used for table names or ORDER BY columns?
- Q538Why should you compare secrets with crypto/subtle.ConstantTimeCompare instead of ==? How do you hash passwords in Go?