January 5, 2023

Представлен Go 1.20 RC2

Представлен второй релиз-кандидат Go 1.20. Что нового:

Изменения на уровне языка

  • Расширены возможности по приведению слайсов к поинтерам на массив. Например, теперь можно писать [4]byte(x) вместо *(*[4]byte(x)), где x — это слайс;
  • В unsafe добавлены функции SliceData, String и StringData. Данные функции позволяют конструировать и деконструировать строки и слайсы;
  • Спецификация*: теперь поля структур сравниваются по одному за раз в порядке их объявления в структуре. Сравнение прекращается при первом несовпадении;
  • Спецификация*: массивы также теперь сравниваются поэлементно по одному за раз.
  • Типы, которые можно сравнивать, теперь удовлетворяют констрейн comparable, даже если аргументы для параметризованных типов строго сравнивать нельзя.

*Данные изменения представлены только в спецификации и отражают уже существующее поведение компилятора.

Инструменты

  • Скомпилированные пакеты из стандартной библиотеки больше не хранятся в $GOROOT/pkgи не поставляются вместо с Go. Теперь такие пакеты собираются и кэшируются по необходимости. Благодаря этому уменьшился размер дистрибутива Go;
  • Теперь можно передать флаг -C <dir>, чтобы задать рабочую директорию для подкоманды go;
  • go build и go test больше не принимают флаг -i — он был помечен как устаревший ещё в версии 1.16;
  • go generate принимает новый флаг --skip=<pattern>, позволяющий пропустить директивы //go:generate, соответствующие паттерну;
  • Аналогичное нововведение и для go test 👆;
  • go build и go install и некоторые другие команды принимают новый флаг --pgo, который включает profile-guided optimization, а также флаг --cover.

CGO

  • CGO теперь выключен по умолчанию в окружениях без тулчейна для Си;
  • Пакеты в стандартной библиотеке, использующие CGO были переписаны, и теперь они написаны на «чиcтом» Go. Это же относится к рейс-детектору для macOS. Для остальных операционных систем Си всё ещё требуется для запуска рейс-детектора.

Покрытие

  • В Go 1.20 стало возможным собрать покрытие кода не только в юнит-тестах, но и просто в рантайме и интеграционных тестах. Для этого флаг --cover и завезли в go build и go install. При включенном флаге в бинарник с приложением также будет запакован инструментарий для сбора покрытия.

Vet

  • go vet теперь обнаруживает многие места неправильного использование ссылочных переменных;
  • Также встроенный линтер репортит о случаях, когда используется формат 2006-02-01 (yyyy-dd-mm) в функциях time.Format и time.Parse. Данный формат не является частью какого-либо стандарта, однако часто используется по ошибке при попытке соответствовать стандарту ISO 8601 (yyyy-mm-dd).

Рантайм

  • Добавлена поддержка экспериментального способа выделения памяти — memory-safe arena allocation. Данный способ позволяет освобождать много памяти за раз. При правильном использовании это улучшит перфоманс по CPU до 15% в приложениях, часто выделяющих новую память;
  • Некоторые внутренние структуры данных сборщика мусора были улучшены, что снизило оверхед на память и улучшило перфоманс по CPU до 2%.

Компилятор

  • В Go 1.20 в режиме превью появился profile-guided optimization (PGO). PGO позволяет оптимизировать приложения при компиляции на основе данных после профилирования (в данный момент поддерживается только pprof). Так, например, инлайнинг функций теперь работает менее агрессивно, а бенчмарки показывают прирост производительности в 3-4%.
  • Пофикшены некоторые баги, в частности связанные с дженериками;
  • Больше нельзя объявить анонимный циклический интерфейс.

Стандартная библиотека

  • crypto/ecdh — новый пакет для поддержки протокола Диффи – Хеллмана на эллиптических кривых;
  • Появилась возможность соединять несколько ошибок в одну с помощью метода errors.Join;
  • В net/http добавили тип ResponseController, позволяющий чуть удобнее работать с запросами;
  • В httputil для реверс-прокси добавили функцию Rewrite, которая должна послужить заменой функции Director. Новый хук позволяет работать также и со входящими запросами, в отличие от Director;
  • ProxyRequest.SetURL — новый метод, который перенаправляет запрос в указанную точку назначения и устанавливает заголовок Host для исходящего запроса. Может быть использован в качестве замены прокси, создаваемого с помощью функции NewSingleHostReverseProxy;
  • Также добавлен метод ProxyRequest.SetXForwarded для задания соответствующих хедеров. При использовании Rewrite данные хедеры по умолчанию не устанавливаются.
  • И множество минорных изменений.

Полный список изменений: https://tip.golang.org/doc/go1.20