логотип PurpleSchool
логотип PurpleSchool

Sort в Go

Автор

Александр Гольцман

Сортировка — важнейший инструмент работы с данными, позволяющий эффективно упорядочивать и искать информацию. В языке программирования Go пакет sort предоставляет мощные инструменты для сортировки срезов и пользовательских коллекций.

В этой статье я расскажу, как использовать sort в Go для работы со встроенными и пользовательскими типами данных, объясню ключевые концепции, их особенности и покажу примеры реализации.

Основы сортировки в Go

Пакет sort входит в стандартную библиотеку Go и предоставляет функции для сортировки срезов и пользовательских коллекций. Его главная особенность — универсальность: с помощью sort можно упорядочивать не только простые срезы, но и сложные структуры с пользовательской логикой.

Подходы к сортировке:

  • Сортировка готовыми методами (sort.Ints, sort.Strings, sort.Float64s).
  • Использование функции sort.Slice для кастомной логики.
  • Реализация интерфейса sort.Interface для полной настройки порядка.

Сортировка срезов простых типов

Начнём с базового примера. Смотрите, как просто отсортировать числа, строки и другие примитивные типы с помощью готовых функций:

numbers := []int{5, 3, 7, 1, 4}
sort.Ints(numbers)
fmt.Println(numbers) // [1 3 4 5 7]

words := []string{"banana", "apple", "cherry"}
sort.Strings(words)
fmt.Println(words) // [apple banana cherry]

Как это работает:

  • sort.Ints() — сортирует срез целых чисел по возрастанию.
  • sort.Strings() — упорядочивает строки в лексикографическом порядке.

Эти функции просты и эффективны, но подходят только для базовых типов данных. Если нужно работать со структурами или применять особые правила, переходите к следующему методу.

Сортировка срезов по условию с помощью sort.Slice

Если требуется отсортировать данные по определённому критерию, используйте функцию sort.Slice. Здесь вы сами задаёте логику сравнения:

people := []struct {
    Name string
    Age  int
}{
    {"Alice", 30},
    {"Bob", 25},
    {"Charlie", 35},
}

sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

for _, person := range people {
    fmt.Println(person.Name, person.Age)
}

Как это работает:

  • sort.Slice() принимает срез и функцию сравнения.
  • Анонимная функция определяет порядок сортировки. Здесь мы упорядочиваем людей по возрасту.

Преимущества sort.Slice:

  • Простота: не нужно реализовывать интерфейс вручную.
  • Гибкость: можно менять логику на лету.

Недостатки:

  • Менее эффективно при многократной сортировке одной коллекции, так как функция сравнения вызывается многократно.

Создание собственной логики сортировки с sort.Interface

Для полного контроля над процессом сортировки реализуйте интерфейс sort.Interface, который состоит из трёх методов:

  • Len() — возвращает количество элементов.
  • Less(i, j int) bool — определяет порядок.
  • Swap(i, j int) — меняет местами элементы.

Пример: Сортировка строк по длине:

type ByLength []string

func (s ByLength) Len() int           { return len(s) }
func (s ByLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
func (s ByLength) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func main() {
    fruits := []string{"apple", "banana", "kiwi"}
    sort.Sort(ByLength(fruits))
    fmt.Println(fruits) // [kiwi apple banana]
}

Как это работает:

  • ByLength — новый тип, созданный на основе среза строк.
  • Реализованы три метода интерфейса sort.Interface.
  • sort.Sort() сортирует срез согласно заданной логике.

Когда использовать интерфейс sort.Interface:

  • Если нужно многократно сортировать один и тот же тип данных с одной логикой.
  • Когда требуется максимальная производительность.

Оптимизация и производительность

  • Алгоритм: Пакет sort использует комбинацию быстрой сортировки и инсерционной сортировки для повышения эффективности на небольших массивах.
  • Сложность: В среднем O(n log n).
  • Оптимизация через интерфейс: Если вы часто сортируете данные с одной логикой, реализация интерфейса будет эффективнее, чем использование sort.Slice.

Заключение

В Go пакет sort предлагает гибкие инструменты для работы с данными: от простых числовых срезов до сложных структур.

  • Используйте sort.Ints, sort.Strings для стандартных коллекций.
  • Применяйте sort.Slice для быстрой сортировки по условию.
  • Реализуйте sort.Interface для полной кастомизации логики.

sort — мощный инструмент, встроенный в стандартную библиотеку Go. Смотрите, как легко управлять упорядочиванием данных — от простых списков до сложных коллекций. Используйте подходящий метод в зависимости от ваших задач, чтобы добиться максимальной эффективности и удобства.

Стрелочка влевоРазделение строк с помощью функции split в GolangПоиск и замена строк в Go - GolangСтрелочка вправо

Постройте личный план изучения Golang до уровня Middle — бесплатно!

Golang — часть карты развития Backend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Golang

Работа с YAML в GolangПреобразование типов в GolangКонвертация структур в JSON в GolangStrconv в GolangИспользование пакета SQLx для работы с базами данных в GolangРазбираемся с SQL в GolangРазделение строк с помощью функции split в GolangSort в GoПоиск и замена строк в Go - GolangИспользование пакета reflect в GolangРабота с PostgreSQL в GoPointers в GolangПарсинг в GoРабота со списками (list) в GolangПреобразование int в string в GolangРабота с числами с плавающей точкой в GolangРабота с полями в GolangИспользование enum в GolangОбработка JSON в GoЧтение и запись CSV-файлов в GolangРабота с cookie в GolangРегистры в GoКэширование данных в GolangПреобразование byte в string в GolangByte в GoИспользование bufio для работы с потоками данных в GolangДобавление данных и элементов (add) в Go
Работа с Docker-контейнерами в GoЛогирование в Golang. Zap, Logrus, Loki, GrafanaИспользование pprof в GolangМеханизмы синхронизации в GolangРабота с пакетом S3 в GolangОптимизация проектов на GoМониторинг Golang приложений с помощью PrometheusПаттерны проектирования в GolangМиграции базы данных в GolangОркестрация контейнеров Go с Kubernetes + DockerGjGo Playground и компилятор GolangИспользование go mod init для создания модулей GolangРабота с переменными окружения (env) в GolangКоманда go build в GolangАвтоматизация Golang проектов — CI/CD с GitLab CI и JenkinsОтладка кода в GolangЧтение и использование конфигурации в приложениях на GolangКомпиляция в GolangКак развернуть Go-приложение на облаке AWSАутентификация в Golang
Сетевые протоколы в GoПеременные в GolangЗначения в GolangДженерик %T и его применение в GolangТипы данных в GolangИспользование tls в GolangИспользование tag в структурах GolangSwitch в GoСтроки в GolangРабота с потоками (stream) в GolangSelect в GoРуны в GoРабота с пакетом params в GolangКонвертация строк в числа в GolangNull, Nil, None, 0 в GoInt в GolangНаименования переменных, функций и структур в GoУстановка GolangЧтение и установка HTTP заголовков в GolangMethods в GolangGoLand — IDE для разработки на Golang от JetBrainsОбработка «not found» в GolangFloat в GolangФлаги командной строки в Go (Golang)Запуск внешних команд в GolangОбработка ошибок в GoИспользование defer в GolangЗначения default в GolangГенерация кода в GoФорматирование кода в GolangЧистая архитектура в GolangКаналы (channels) в GolangПолучение body из HTTP запроса в Golang
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы Golang

Антон Ларичев
иконка часов19 бесплатных уроков
иконка звёздочки рейтинга4.7
Backend
изображение курса

Nest.js с нуля

Антон Ларичев
иконка часов11 бесплатных уроков
иконка звёздочки рейтинга4.6
Backend
изображение курса

Docker и Ansible

Антон Ларичев
иконка часов19 бесплатных уроков
иконка звёздочки рейтинга4.8
Backend
DevOps