Ответ
В Go идиоматический способ сортировки — использование пакета sort
. Он предоставляет эффективные и гибкие инструменты для работы с любыми типами данных.
В основе пакета лежит интерфейс sort.Interface
:
_type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
_```
Любой тип, реализующий этот интерфейс, может быть отсортирован функцией `sort.Sort()`.
### Способы сортировки пользовательских типов:
**1. Реализация `sort.Interface` (классический способ)**
Нужно определить три метода для вашего типа-слайса. Это полезно, когда сортировка является основным поведением для типа.
```go
_type User struct {
Name string
Age int
}
// ByAge реализует sort.Interface для []User по полю Age
_type ByAge []User
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
users := []User{
{"Alice", 25},
{"Bob", 20},
}
sort.Sort(ByAge(users))
fmt.Println(users) // [{Bob 20} {Alice 25}]
}
_```
**2. Использование `sort.Slice` (современный и более гибкий способ)**
Эта функция, появившаяся в Go 1.8, не требует реализации интерфейса. Она принимает слайс и функцию `less` в качестве аргументов. Это удобнее для одноразовых или динамических сортировок.
```go
_func main() {
users := []User{
{"Alice", 25},
{"Bob", 20},
}
// Сортировка по имени
sort.Slice(users, func(i, j int) bool {
return users[i].Name < users[j].Name
})
fmt.Println(users) // [{Alice 25} {Bob 20}]
}
_```
### Алгоритм и готовые функции
- **Алгоритм**: Стандартная библиотека Go использует **pdqsort** (Pattern-Defeating Quicksort), который является гибридом быстрой сортировки, пирамидальной сортировки и сортировки вставками. Он показывает отличную производительность в большинстве случаев.
- **Готовые функции**: Для базовых типов существуют удобные обертки, такие как `sort.Ints()`, `sort.Float64s()` и `sort.Strings()`, которые используют те же эффективные алгоритмы.