Какие ключевые изменения в Go, начиная с версии 1.18, вы считаете наиболее важными и почему?

Ответ

Это отличный вопрос для оценки того, насколько кандидат следит за развитием языка. Начиная с версии 1.18, в Go произошли фундаментальные изменения.

Ключевые из них:

1. Дженерики (Generics) — Go 1.18

Это самое значительное изменение в истории языка. Дженерики (параметрический полиморфизм) позволяют писать функции и типы данных, которые работают с любым типом из определённого набора.

  • Почему это важно: Устраняет необходимость в дублировании кода для разных типов (например, MaxInt, MaxFloat64) или использовании interface{} с последующим приведением типов, что было менее безопасно и производительно.
// Пример обобщенной функции для поиска минимального элемента
func Min[T constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

// fmt.Println(Min(10, 20))       // Работает с int
// fmt.Println(Min(10.5, 20.2))   // Работает с float64

2. Рабочие области (Workspaces) — Go 1.18

Режим go work позволяет одновременно работать с несколькими модулями, как если бы они находились в одном. Это упрощает разработку проектов, состоящих из нескольких микросервисов или библиотек.

  • Почему это важно: Больше не нужно использовать директивы replace в go.mod для локальной разработки, что было неудобно и приводило к ошибкам.

3. Оптимизация на основе профиля (Profile-Guided Optimization, PGO) — Go 1.20+

PGO позволяет компилятору использовать данные профилирования (информацию о том, какие части кода выполняются чаще всего) для более эффективной оптимизации приложения.

  • Почему это важно: Может автоматически повысить производительность приложения на 2-7% без изменения кода, просто за счёт сбора профиля на реальных нагрузках и пересборки с ним.

4. Новые функции в стандартной библиотеке

  • slices и maps (Go 1.21): Появились новые пакеты для удобной работы со срезами и картами, использующие дженерики (например, slices.Sort, slices.Compact, maps.Keys).
  • slog (Go 1.21): Новый пакет для структурированного логирования, ставший стандартом де-факто.

Ответ 18+ 🔞

Да ты посмотри, какие времена настали, а? Раньше, блядь, в Го сидел, как дурак, и писал для каждого типа свою функцию — MaxInt, MaxFloat, MaxString — пиздец, а не жизнь. А теперь, ёпта, с версии 1.18, как с цепи сорвались!

Первое и главное — дженерики, блядь! Наконец-то можно не костылять через interface{}, который потом на каждом шагу кастить надо, а писать нормально. Смотри, как красота:

func Min[T constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

Вот и всё, мать его! Одна функция и для интов, и для флоатов, и для строк. Красота, а не жизнь. Раньше бы на это три файла нахуярил, а теперь — в одну строку, и доволен, как слон.

Второе — рабочие области, workspaces. Раньше, сука, если два модуля локально разрабатывал, так в go.mod лез, там replace писал, потом забывал убрать, в прод пулял — и пиздец наступал. А теперь команда go work — и сидишь, как царь, все модули в одном пространстве, и ни одна замена в продакшене не всплывёт. Удобно, блядь, до охуения.

Третье — PGO, оптимизация по профилю. Это вообще магия какая-то, ёперный театр! Запустил приложение, собрал данные, где какие циклы чаще крутятся, отдал компилятору — и он сам, хитрая жопа, пересоберёт всё так, чтобы быстрее работало. Говорят, на 2-7% производительность поднимает, просто так, на ровном месте. Волшебство, блядь, а не фича.

Ну и библиотеки новые подтянулись. В 1.21, например, пакеты slices и maps появились. Теперь не надо самому писать сортировку или выковыривать ключи из мапы — всё уже есть, готовое, на дженериках. И slog для логирования — теперь структурированные логи стали стандартом, а не через fmt.Println или левые библиотеки.

В общем, Го уже не тот суровый уёбок, что был десять лет назад. Эволюционирует, блядь, в хорошую сторону. Кто говорит, что язык простой и скучный — тот просто не в курсе, какие распиздяйства теперь можно творить!