Мы в МТС очень много всего разрабатываем на Golang, поскольку считаем этот язык программирования весьма достойным для проектов разного масштаба. На нём относительно просто писать, т. е. увеличивается скорость разработки, производительность — высокая, плюс есть защита от ошибок. И вот на днях был представлен Go 1.21. Что улучшили, изменили и добавили?  Разработчики внесли небольшое изменение в нумерацию версий. Так, ранее нумерация была представлена в форме Go 1.x для обозначения как глобальной версии языка Go, так и семейства версий, а также первой версии этого семейства. Теперь всё немного иначе. Начиная с Go 1.21, первая версия теперь — Go 1.X.0. Вот здесь представлено подробное описание того, как это работает сейчас.  Кроме того, сейчас реализована поддержка оптимизаций на основе результатов профилирования кода. Речь идёт о PGO — Profile-guided optimization. Одна из положительных черт поддержки — учёт особенностей, которые определяются во время выполнения программы. Соответственно, учёт профиля выполнения при сборке даёт возможность увеличить производительность приложений от 2% до 7%.  Улучшен вывод типов в обобщённых функциях, т. е. дженериках, которые предназначены для работы сразу с несколькими типами.  Плюс ко всему добавлена экспериментальная поддержка новой семантики обработки переменных в циклах. Соответственно, можно избежать типовых ошибок вследствие специфического поведения при использовании замыканий с подпрограмм в итерациях. Также можно отметить то, что новая семантика предусматривает создание для каждой итерации цикла отдельного экземпляра переменной. Она объявляется в цикле “for” при помощи оператора “:=”. Разработчики добавили в стандартную библиотеку новые пакеты, включая:  log/slog — функции для записи структурированных логов slices — типовые операции со срезами (slice) любых типов. Например, предложены функции для сортировки, более быстрые и гибкие, чем функции из пакета sort maps — полезные операции над отображениями (map) с любыми типами ключей и элементов cmp — функции для сравнений упорядоченных значений   Компилятор пересобрали с добавлением PGO-оптимизаций. Это даёт возможность ускорить сборку программ на 2–4%. Не так много, но и немало. Оптимизирован сборщик мусора, что дало возможность снизить задержки в ряде приложений вплоть до 40%.  Удалось снизить накладные расходы при трассировке кода при помощи пакета runtime/trace на системах с архитектурой amd64 и arm64.  Добавлены новые функции, включая min и max, для выбора наименьшего/наибольшего значения, а также функция clear для удаления или обнуления всех элементов в структурах map или slice. Ну и последнее: в новой версии появился экспериментальный порт (GOOS=wasip1, GOARCH=wasm) для компиляции в промежуточный код WebAssembly, использующий API WASI (WebAssembly System Interface) для обеспечения обособленного запуска.  Как и говорилось выше, их три — это min и max, а также clear. min и max Они позволяют выбирать наименьшее и наибольшее значение из переданных. Вот как это работает:  n := min(10, 3, 22) fmt.Println(m) // 3 n := max(10, 3, 22) fmt.Println(m) // 22 Кроме того, эти функции могут принимать значения упорядоченных типов (ordered type): целые числа, вещественные числа или строки (а также производные от них): x := min(9.99, 3.14, 5.27) fmt.Println(x) // 3.14   s := min("one", "two", "three") fmt.Println(s) // "one"   type ID int   id1 := ID(7) id2 := ID(42) id := max(id1, id2) fmt.Println(id) // 42 Функции принимают один или больше аргументов:  fmt.Println(min(10)) // 10 fmt.Println(min(10, 9)) // 9 fmt.Println(min(10, 9, 8)) // 8 // .. В то же время они не являются вариационными. Если попробовать, то появится ошибка: nums := []int{10, 9, 8} n := min(nums...) // Error: invalid operation: invalid use of ... with built-in min Clear  Эта функция работает со срезами, картами и type parameter values. Вот как clear удаляет все элементы из карты:  m := map[string]int{"one": 1, "two": 2, "three": 3} clear(m)   fmt.Printf("%#v\n", m) // Output: map[string]int{} С другой стороны, со срезами всё несколько иначе. Здесь функция обнуляет отдельные элементы без изменения длины:  s := []string{"one", "two", "three"} clear(s)   fmt.Printf("%#v\n", s) // []string{"", "", ""} Clear не может изменить длину среза, но вполне в состоянии изменить значения элементов массива, который находится непосредственно под срезом. Ну а карта — указатель на структуру вида, поэтому противоречий в том, что clear удаляет элементы из карты, нет.  Ну и последнее — по поводу type parameter values. Вот как это работает:  func customClear [T []string | map[string]int] (container T) {     clear(container) }   s := []string{"one", "two", "three"} customClear(s) fmt.Printf("%#v\n", s) // []string{"", "", ""}   m := map[string]int{"one": 1, "two": 2, "three": 3} customClear(m) fmt.Printf("%#v\n", m) // map[string]int{} Получается, что customClear принимает аргумент container. Он может быть или срезом, или картой. А clear внутри функции занимается обработкой container в соответствии с типом: карты очищаются, а у срезов обнуляются элементы.  Важный момент — сlear не может работать с массивами.  arr := [3]int{1, 2, 3} clear(arr) // invalid argument: argument must be (or constrained by) map or slice Вот полный список встроенных функций в Go 1.21:  appendr — добавляет значения в срез Clear — удаляет или зануляет элементы контейнера closer — закрывает канал Complexr, real, imag — создают и разбирают комплексные числа  deleter — удаляет элемент карты по ключу lenr — возвращает длину контейнера capr — возвращает вместимость контейнера maker — создаёт новый срез, карту или канал newr — выделяет память под переменную minr — выбирает минимальный из переданных аргументов maxr — выбирает максимальный из переданных аргументов Panicr и recover — создают и обрабатывают панику print и println — печатают аргументы Ну а на этом всё. Если вы уже работали с новой версией языка, расскажите, что понравилось, что нет, чего ещё ждёте.