пятница, 18 октября 2024 г.

Как итерировать по символам в строках Go

В Go итерация по строке по ее символам (или знакам) может быть выполнена несколькими различными способами.

Использование цикла for...range

Наиболее распространенный и идиоматический способ итерации по строке в Go — использование цикла for...range. Этот метод правильно обрабатывает символы Unicode, рассматривая каждый символ как руну (что является псевдонимом для int32). Вот пример:

package main

import "fmt"

func main() {
    str := "Hello, 世界" // Строка с символами ASCII и не-ASCII

    for index, char := range str {
        fmt.Printf("Index: %d, Character: %c\n", index, char)
    }
}

Вывод:

Index: 0, Character: H
Index: 1, Character: e
Index: 2, Character: l
Index: 3, Character: l
Index: 4, Character: o
Index: 5, Character: ,
Index: 6, Character:
Index: 7, Character: 世
Index: 8, Character: 界

Использование стандартного цикла for с рунами

Если вы предпочитаете использовать традиционный цикл for, вы можете преобразовать строку в срез рун. Это позволяет вам перебирать каждый символ, сохраняя правильное представление символов Unicode:

package main

import "fmt"

func main() {
    str := "Hello, 世界"
    runes := []rune(str) // Преобразовать строку в срез рун

    for i := 0; i < len(runes); i++ {
        fmt.Printf("Rune %d is '%c'\n", i, runes[i])
    }
}

Вывод:

Rune 0 is 'H'
Rune 1 is 'e'
Rune 2 is 'l'
Rune 3 is 'l'
Rune 4 is 'o'
Rune 5 is ','
Rune 6 is ' '
Rune 7 is '世'
Rune 8 is '界'

Использование метода strings.Split

Другой подход — использовать метод strings.Split для разделения строки на отдельные символы. Однако этот метод может быть не таким эффективным или идиоматичным, как предыдущие методы:

package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "Hello, 世界"
    chars := strings.Split(str, "") // Разделить строку на отдельные символы

    for _, char := range chars {
        fmt.Printf("Character: %s\n", char)
    }
}

Вывод:

Character: H
Character: e
Character: l
Character: l
Character: o
Character: ,
Character:
Character: 世
Character: 界

В Go предпочтительным способом перебора строк по символам является использование цикла for...range, поскольку он автоматически обрабатывает кодировку UTF-8 и обеспечивает простой способ доступа к каждому символу как к руне. В качестве альтернативы преобразование строки в срез рун обеспечивает больший контроль с помощью традиционной индексации. Метод strings.Split также можно использовать, но он менее эффективен для этой цели. Понимание этих методов поможет вам эффективно работать со строками в Go.


Читайте также:


Строки как тип данных в Go

В Go (Golang) строка — это фундаментальный тип данных, используемый для представления последовательности символов. Он широко используется для обработки текста и необходим для различных задач программирования.

Характеристики строк в Go

Неизменяемость - после создания строки ее значение не может быть изменено. Любая операция, которая, как кажется, изменяет строку, на самом деле создает новую строку. Эта неизменяемость помогает оптимизировать использование памяти и обеспечить безопасность потоков.

Кодировка UTF-8 - строки в Go по умолчанию кодируются в UTF-8, что позволяет им представлять широкий спектр символов из разных языков. Каждый символ может занимать один или несколько байтов, что делает его гибким для интернационализации.

Срез байтов только для чтения - строку можно рассматривать как срез байтов только для чтения. Это означает, что хотя вы можете получить доступ к байтам, составляющим строку, вы не можете изменять их напрямую.

Создание строк

Строки в Go можно создавать с помощью двойных кавычек для интерпретируемых литералов или обратных кавычек для необработанных литералов.

Интерпретируемые литералы - поддерживают escape-последовательности (например, "\n" для новой строки).

str1 := "Hello, World!"

Необработанные литералы - заключены в обратные кавычки, они не поддерживают escape-последовательности и могут охватывать несколько строк.

str2 := `Это необработанный строковый литерал,
который может охватывать несколько строк.`

Операции и функции со строками

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

Длина - используйте len() для получения количества байтов в строке.

length := len(str1) // Возвращает длину str1

Конкатенация - строки можно объединять с помощью оператора +.

combined := str1 + " " + str2

Подстрока - можно извлекать подстроки с помощью синтаксиса среза.

sub := str1[0:5] // "Hello"

Поиск и замена - функции, такие как strings.Contains(), strings.Replace() и strings.Index(), помогают находить подстроки или заменять части строк.

Пример кода

Вот простой пример, демонстрирующий создание строки и некоторые базовые операции:

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Создание строк
    greeting := "Hello"
    name := "World"

    // Объединение строк
    message := greeting + ", " + name + "!"
    fmt.Println(message) // Вывод: Hello, World!

    // Проверка длины
    fmt.Println("Длина:", len(message)) // Вывод: Длина: 13

    // Поиск подстроки
    index := strings.Index(message, "World")
    fmt.Println("Индекс 'World':", index) // Вывод: Индекс 'World': 7

    // Замена подстроки
    newMessage := strings.Replace(message, "World", "Gopher", 1)
    fmt.Println(newMessage) // Вывод: Hello, Gopher!
}

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


Читайте также:


пятница, 27 сентября 2024 г.

Где в памяти располагаются переменные в Golang

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

На стеке

Переменные размещаются на стеке (stack), когда они локальны для функции или метода. Например, если переменная объявлена внутри функции:

func main() {
    var myVar string // Переменная 'myVar' будет находиться на стеке
}

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

В куче (heap)

Переменная будет находиться в куче, если она является глобальной или создана с использованием ключевого слова new.

Глобальные переменные

package main

var myVar string // Переменная 'myVar' будет находиться в куче

func main() {}

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

Создание переменной через new

package main

import "fmt"

func main() {
    var myVar *string = new(string) // Переменная 'myVar' будет находиться в куче
    fmt.Println(*myVar)             // Результат будет nil
    
    *myVar = "Hello, World!"        // Заполнение значения по адресу переменной
    fmt.Println(*myVar)             // Вывод: Hello, World!
}

При использовании оператора new, создается новая область памяти в куче и возвращается ее адрес.

Таким образом, чтобы определить, где именно в памяти находится переменная, нужно проанализировать её использование в коде:

  • Если переменная локальна для функции, то она будет находиться на стеке.
  • Если она является глобальной, то будет находиться в куче.
  • Если использовалось ключевое слово new, то она также будет находиться в куче.

Читайте также:


Как Golang работает с памятью

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

Автоматическое управление памятью

Компилятор Go автоматически выделяет и освобождает память для переменных и структур данных. Когда переменная выходит из области видимости, ее память автоматически освобождается за счет работы сборщика мусора. Это упрощает написание программ и уменьшает количество ошибок, связанных с утечками памяти.

Память, выделенная в стеке

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

Динамическая память (куча, heap)

Переменные, созданные с помощью оператора new, размещаются в куче. Куча используется для хранения объектов, которые должны существовать дольше одной функции. Управление памятью в куче осуществляется через сборщик мусора, который периодически сканирует память и освобождает объекты, на которые больше нет ссылок.

Сборка мусора

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

Безопасность памяти

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

Высокая производительность

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


Читайте также:


среда, 28 августа 2024 г.

Релиз Go 1.23

Релиз Go 1.23, выходит через шесть месяцев после Go 1.22. Большинство изменений в нем касаются реализации цепочки инструментов, среды выполнения и библиотек. Как всегда, релиз сохраняет обещание совместимости Go 1. Ожидается, что почти все программы Go продолжат компилироваться и запускаться, как и прежде.

Изменения в языке

Go 1.23 делает эксперимент (Go 1.22) "range-over-func" частью языка. "range" в цикле "for-range" теперь принимает функции итератора следующих типов

func(func() bool)
func(func(K) bool)
func(func(K, V) bool)

как выражения диапазона. Вызовы функции аргумента итератора создают значения итерации для цикла "for-range".

Go 1.23 включает предварительную поддержку псевдонимов универсальных типов. Создание цепочки инструментов с GOEXPERIMENT=aliastypeparams включает эту функцию в пакете. (Использование универсальных псевдонимов за пределами границ пакета пока не поддерживается.)

Инструменты

Телеметрия

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

Телеметрия Go — это включаемая по настройке система, управляемая командой go telemetry. По умолчанию программы цепочки инструментов собирают статистику в файлах счетчиков, которые можно проверять локально, но в остальном не используются (локальная телеметрия go).

Чтобы помочь разработчикам языка поддерживать хорошую работу Go и понимать использование Go рассмотрите возможность включения телеметрии Go, запустив go telemetry on. В этом режиме анонимные отчеты счетчиков еженедельно загружаются на telemetry.go.dev, где они объединяются в графики и также становятся доступными для загрузки любыми участниками Go или пользователями, желающими проанализировать данные.

Команда Go

Установка переменной среды GOROOT_FINAL больше не имеет эффекта. Дистрибутивы, которые устанавливают команду go в местоположение, отличное от $GOROOT/bin/go, должны устанавливать символическую ссылку вместо перемещения или копирования двоичного файла go.

Новый флаг go env -changed заставляет команду печатать только те настройки, эффективное значение которых отличается от значения по умолчанию, которое было бы получено в пустой среде без предварительного использования флага -w.

Новый флаг go mod tidy -diff заставляет команду не изменять файлы, а вместо этого печатать необходимые изменения в виде единого diff. Он завершается с ненулевым кодом, если требуются обновления.

Команда go list -m -json теперь включает новые поля Sum и GoModSum. Это похоже на существующее поведение команды go mod download -json.

Новая директива godebug в go.mod и go.work объявляет настройку GODEBUG для применения к используемому рабочему модулю или рабочему пространству.

Vet

Подкоманда go vet теперь включает анализатор stdversion, который помечает ссылки на символы, которые слишком новые для версии Go, действующей в ссылающемся файле. (Эффективная версия определяется директивой go в файле go.mod, включающем файл, и любыми ограничениями //go:build в файле.)

Например, она выдаст диагностику для ссылки на функцию reflect.TypeFor (введенную в go1.22) из ​​файла в модуле, файл go.mod которого указывает go 1.21.

Cgo

cmd/cgo поддерживает новый флаг -ldflags для передачи флагов компоновщику C. Команда go использует его автоматически, избегая ошибок “argument list too long” ("слишком длинный список аргументов") с очень большим CGO_LDFLAGS.

Trace

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

Среда выполнения

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

Компилятор

Накладные расходы на сборку с Profile Guided Optimization были значительно сокращены. Ранее большие сборки могли увидеть увеличение времени сборки на 100%+ при включении PGO. В Go 1.23 накладные расходы должны быть в однозначных процентах.

Компилятор в Go 1.23 теперь может перекрывать слоты кадра стека локальных переменных, доступных в непересекающихся областях функции, что снижает использование стека для приложений Go.

Для 386 и amd64 компилятор будет использовать информацию из PGO для выравнивания определенных горячих блоков в циклах. Это повышает производительность еще на 1-1,5% за счет дополнительных 0,1% размера текста и двоичного кода. В настоящее время это реализовано только на 386 и amd64, поскольку не показало улучшения на других платформах. Выравнивание горячих блоков можно отключить с помощью -gcflags=[<packages>=]-d=alignhot=0.

Компоновщик

Теперь компоновщик запрещает использовать директиву //go:linkname для ссылки на внутренние символы в стандартной библиотеке (включая среду выполнения), которые не отмечены //go:linkname в своих определениях. Аналогично компоновщик запрещает ссылки на такие символы из ассемблерного кода. Для обратной совместимости существующие использования //go:linkname, найденные в большом количестве открытого исходного кода, остаются поддерживаемыми. Любые новые ссылки на внутренние символы стандартной библиотеки будут запрещены.

Флаг командной строки компоновщика -checklinkname=0 можно использовать для отключения этой проверки в целях отладки и экспериментирования.

При сборке динамически связанного двоичного файла ELF (включая двоичный файл PIE) новый флаг -bindnow включает немедленное связывание функций.

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

Изменения таймера

Go 1.23 вносит два существенных изменения в реализацию time.Timer и time.Ticker.

Во-первых, таймеры и тикеры, на которые больше не ссылается программа, немедленно становятся доступными для сборки мусора, даже если их методы Stop не были вызваны. Более ранние версии Go не собирали неостановленные таймеры до тех пор, пока они не сработают, и никогда не собирали неостановленные тикеры.

Во-вторых, канал таймера, связанный с таймером или тикером, теперь не буферизован, с емкостью 0. Основной эффект этого изменения заключается в том, что Go теперь гарантирует, что для любого вызова метода Reset или Stop никакие устаревшие значения, подготовленные до этого вызова, не будут отправлены или получены после вызова. Более ранние версии Go использовали каналы с одноэлементным буфером, что затрудняло правильное использование Reset и Stop. Видимым эффектом этого изменения является то, что len и cap каналов таймера теперь возвращают 0 вместо 1, что может повлиять на программы, которые опрашивают длину, чтобы решить, будет ли прием на канале таймера успешным. Такой код должен использовать неблокируемый прием вместо этого.

Эти новые поведения включаются только тогда, когда основная программа Go находится в модуле со строкой go в go.mod, использующей Go 1.23.0 или более позднюю версию. Когда Go 1.23 собирает старые программы, старые поведения остаются в силе. Новая настройка GODEBUG asynctimerchan=1 может использоваться для возврата к асинхронному поведению канала, даже если программа называет Go 1.23.0 или более позднюю версию в своем файле go.mod.

Новый пакет unique

Новый пакет unique предоставляет возможности для канонизации значений (например, "интернирование" или "хэш-консинг").

Любое значение сопоставимого типа может быть канонизировано с помощью новой функции Make[T], которая создает ссылку на каноническую копию значения в форме Handle[T]. Два Handle[T] равны тогда и только тогда, когда значения, используемые для создания дескрипторов, равны, что позволяет программам дедуплицировать значения и уменьшать свой объем памяти. Сравнение двух значений Handle[T] эффективно, сводясь к простому сравнению указателей.

Итераторы

Новый пакет iter предоставляет основные определения для работы с пользовательскими итераторами.

Пакет slices добавляет несколько функций, которые работают с итераторами:

  • All возвращает итератор по индексам и значениям среза.
  • Values возвращает итератор по элементам среза.
  • Backward возвращает итератор, который проходит по срезу в обратном направлении.
  • Collect собирает значения из итератора в новый срез.
  • AppendSeq добавляет значения из итератора в существующий срез.
  • Sorted собирает значения из итератора в новый срез, а затем сортирует срез.
  • SortedFunc похож на Sorted, но с функцией сравнения.
  • SortedStableFunc похож на SortFunc, но использует стабильный алгоритм сортировки.
  • Chunk возвращает итератор по последовательным подсрезам до n элементов среза.

Пакет maps добавляет несколько функций, которые работают с итераторами:

  • All возвращает итератор по парам ключ-значение из карты.
  • Keys возвращает итератор по ключам в карте.
  • Values возвращает итератор по значениям в карте.
  • Insert добавляет пары ключ-значение из итератора в существующую карту.
  • Collect собирает пары ключ-значение из итератора в новую карту и возвращает ее.

Новый пакет structs

Новый пакет structs предоставляет типы для полей структур, которые изменяют свойства содержащего типа структуры, такие как макет памяти.

В этом релизе единственным таким типом является HostLayout, который указывает, что структура с полем этого типа имеет макет, который соответствует ожиданиям платформы хоста. HostLayout следует использовать в типах, которые передаются, возвращаются или доступны через указатель, переданный в/из API хоста. Без этого маркера порядок макета структур не гарантируется спецификацией языка, хотя с версии Go 1.23 макеты хоста и языка совпадают.

Незначительные изменения в библиотеке

archive/tar

Если аргумент FileInfoHeader реализует новый интерфейс FileInfoNames, то методы интерфейса будут использоваться для установки Uname/Gname заголовка файла. Это позволяет приложениям переопределять зависящий от системы поиск Uname/Gname.

crypto/tls

Клиент TLS теперь поддерживает черновую спецификацию Encrypted Client Hello. Эту функцию можно включить, установив поле Config.EncryptedClientHelloConfigList в закодированный ECHConfigList для хоста, к которому выполняется подключение.

Тип QUICConn, используемый реализациями QUIC, включает новые события, сообщающие о состоянии возобновления сеанса, и предоставляет способ для уровня QUIC добавлять данные в билеты сеанса и записи кэша сеанса.

Наборы шифров 3DES были удалены из списка по умолчанию, используемого, когда Config.CipherSuites равен нулю. Значение по умолчанию можно вернуть, добавив tls3des=1 в переменную среды GODEBUG.

Экспериментальный постквантовый механизм обмена ключами X25519Kyber768Draft00 теперь включен по умолчанию, когда Config.CurvePreferences равен нулю. Значение по умолчанию можно вернуть, добавив tlskyber=0 в переменную среды GODEBUG.

В версии 1.23 поведение X509KeyPair и LoadX509KeyPair изменено для заполнения поля Certificate.Leaf возвращаемого сертификата. Для этого поведения добавлен новый параметр x509keypairleaf GODEBUG.

crypto/x509

CreateCertificateRequest теперь правильно поддерживает алгоритмы подписи RSA-PSS.

CreateCertificateRequest и CreateRevocationList теперь проверяют сгенерированную подпись с помощью открытого ключа подписчика. Если подпись недействительна, возвращается ошибка. Это поведение CreateCertificate с версии Go 1.16.

Параметр x509sha1 GODEBUG будет удален в следующем основном релизе Go (Go 1.24). Это будет означать, что crypto/x509 больше не будет поддерживать проверку подписей на сертификатах, использующих алгоритмы подписи на основе SHA-1.

Новая функция ParseOID анализирует строку идентификатора объекта ASN.1, закодированную точками. Тип OID теперь реализует интерфейсы encoding.BinaryMarshaler, encoding.BinaryUnmarshaler, encoding.TextMarshaler, encoding.TextUnmarshaler.

database/sql

Ошибки, возвращаемые реализациями driver.Valuer, теперь заключены в оболочку для улучшенной обработки ошибок во время таких операций, как DB.Query, DB.Exec и DB.QueryRow.

debug/elf

Пакет debug/elf теперь определяет PT_OPENBSD_NOBTCFI. Этот ProgType используется для отключения принудительного применения Branch Tracking Control Flow Integrity (BTCFI) в двоичных файлах OpenBSD.

Теперь определяет константы типа символа STT_RELC, STT_SRELC и STT_GNU_IFUNC.

coding/binary

Новые функции Encode и Decode являются эквивалентами байтовых срезов Read и Write. Append позволяет объединять несколько данных в один байтовый срез.

go/ast

Новая функция Preorder возвращает удобный итератор по всем узлам синтаксического дерева.

go/types

Тип Func, представляющий символ функции или метода, теперь имеет метод Func.Signature, который возвращает тип функции, который всегда является Signature.

Тип Alias теперь имеет метод Rhs, который возвращает тип в правой части его объявления: учитывая тип A = B, Rhs A равен B.

Были добавлены методы Alias.Origin, Alias.SetTypeParams, Alias.TypeParams и Alias.TypeArgs. Они необходимы для типов-псевдонимов.

По умолчанию go/types теперь создает узлы типа Alias ​​для псевдонимов типов. Это поведение можно контролировать с помощью флага GODEBUG gotypesalias. Его значение по умолчанию изменилось с 0 в Go 1.22 на 1 в Go 1.23.

math/rand/v2

Были добавлены функция Uint и метод Rand.Uint. Они были непреднамеренно исключены из Go 1.22.

Новый метод ChaCha8.Read реализует интерфейс io.Reader.

net

Новый тип KeepAliveConfig позволяет настраивать параметры поддержки активности для TCP-соединений с помощью нового метода TCPConn.SetKeepAliveConfig и новых полей KeepAliveConfig для Dialer и ListenConfig.

Тип DNSError теперь оборачивает ошибки, вызванные тайм-аутами или отменой. Например, error.Is(someDNSErr, context.DeadlineExceedeed) теперь будет сообщать, была ли ошибка DNS вызвана тайм-аутом.

Новый параметр GODEBUG netedns0=0 отключает отправку дополнительных заголовков EDNS0 в запросах DNS, поскольку, как сообщается, они нарушают работу DNS-сервера на некоторых модемах.

net/http

Cookie теперь сохраняет двойные кавычки вокруг значения cookie. Новое поле Cookie.Quoted указывает, было ли Cookie.Value изначально закавычено.

Новый метод Request.CookiesNamed извлекает все cookie, соответствующие заданному имени.

Новое поле Cookie.Partitioned идентифицирует файлы cookie с атрибутом Partitioned.

Шаблоны, используемые ServeMux, теперь допускают один или несколько пробелов или табуляций после имени метода. Ранее разрешался только один пробел.

Новая функция ParseCookie анализирует значение заголовка Cookie и возвращает все файлы cookie, которые были установлены в нем. Поскольку одно и то же имя файла cookie может встречаться несколько раз, возвращаемые значения могут содержать более одного значения для данного ключа.

Новая функция ParseSetCookie анализирует значение заголовка Set-Cookie и возвращает файл cookie. Она возвращает ошибку при синтаксической ошибке.

ServeContent, ServeFile и ServeFileFS теперь удаляют заголовки Cache-Control, Content-Encoding, Etag и Last-Modified при обслуживании ошибки. Эти заголовки обычно применяются к содержимому без ошибок, но не к тексту ошибок.

Промежуточное ПО, которое оборачивает ResponseWriter и применяет кодирование "на лету", например Content-Encoding: gzip, не будет работать после этого изменения. Предыдущее поведение ServeContent, ServeFile и ServeFileFS можно восстановить, установив GODEBUG=httpservecontentkeepheaders=1.

Обратите внимание, что промежуточное ПО, которое изменяет размер обслуживаемого контента (например, сжимая его), уже не работает должным образом, когда ServeContent обрабатывает запрос Range. Сжатие "на лету" должно использовать заголовок Transfer-Encoding вместо Content-Encoding.

Для входящих запросов новое поле Request.Pattern содержит шаблон ServeMux (если есть), который соответствует запросу. Это поле не задается, если задано GODEBUG=httpmuxgo121=1.

net/http/httptest

Новый метод NewRequestWithContext создает входящий запрос с context.Context.

net/netip

В Go 1.22 и более ранних версиях использование reflect.DeepEqual для сравнения Addr, содержащего адрес IPv4, с Addr, содержащим форму IPv6, сопоставленную с IPv4, неправильно возвращало значение true, даже если значения Addr отличались при сравнении с == или Addr.Compare. Теперь эта ошибка исправлена, и все три подхода теперь выдают одинаковый результат.

os

Функция Stat теперь устанавливает бит ModeSocket для файлов, которые являются сокетами Unix в Windows. Эти файлы идентифицируются по тегу повторной обработки, установленному на IO_REPARSE_TAG_AF_UNIX.

В Windows биты режима, сообщаемые Lstat и Stat для точек повторной обработки, изменились. Точки монтирования больше не имеют установленного ModeSymlink, а точки повторной обработки, которые не являются символическими ссылками, сокетами Unix или файлами дедупликации, теперь всегда имеют установленный ModeIrregular. Это поведение контролируется настройкой winsymlink. Для Go 1.23 по умолчанию установлено значение winsymlink=1. Для предыдущих версий по умолчанию установлено значение winsymlink=0.

Функция CopyFS копирует io/fs.FS в локальную файловую систему.

В Windows Readlink больше не пытается нормализовать тома по буквам дисков, что не всегда было возможно. Такое поведение контролируется настройкой winreadlinkvolume. Для Go 1.23 по умолчанию установлено значение winreadlinkvolume=1. Для предыдущих версий по умолчанию установлено значение winreadlinkvolume=0.

В Linux с поддержкой pidfd (обычно Linux v5.4+) функции и методы, связанные с процессами, используют pidfd (а не PID) внутренне, что исключает потенциальное неправильное нацеливание при повторном использовании PID ОС. Поддержка Pidfd полностью прозрачна для пользователя, за исключением дополнительных дескрипторов файлов процессов, которые могут быть у процесса.

path/filepath

Новая функция Localize безопасно преобразует путь, разделенный косой чертой, в путь операционной системы.

В Windows EvalSymlinks больше не оценивает точки монтирования, что было источником многих несоответствий и ошибок. Это поведение контролируется настройкой winsymlink. Для Go 1.23 по умолчанию установлено winsymlink=1. В предыдущих версиях по умолчанию установлено winsymlink=0.

В Windows EvalSymlinks больше не пытается нормализовать тома по буквам дисков, что не всегда было возможно. Это поведение контролируется настройкой winreadlinkvolume. Для Go 1.23 по умолчанию установлено winreadlinkvolume=1. В предыдущих версиях по умолчанию установлено winreadlinkvolume=0.

reflect

В Type добавлены новые методы, синонимичные методам с тем же именем в Value:

  • Type.OverflowComplex
  • Type.OverflowFloat
  • Type.OverflowInt
  • Type.OverflowUint

Новая функция SliceAt аналогична NewAt, но для срезов.

Методы Value.Pointer и Value.UnsafePointer теперь поддерживают значения типа String.

Новые методы Value.Seq и Value.Seq2 возвращают последовательности, которые перебирают значение, как если бы оно использовалось в цикле for/range. Новые методы Type.CanSeq и Type.CanSeq2 сообщают, будет ли вызов Value.Seq и Value.Seq2, соответственно, успешным без паники.

runtime/debug

Функция SetCrashOutput позволяет пользователю указать альтернативный файл, в который среда выполнения должна записать свой отчет о фатальном сбое. Его можно использовать для создания автоматизированного механизма отчетности для всех неожиданных сбоев, а не только для тех, которые находятся в goroutines, которые явно используют recovery.

runtime/pprof

Максимальная глубина стека для профилей alloc, mutex, block, threadcreate и goroutine была увеличена с 32 до 128 кадров.

runtime/trace

Среда выполнения теперь явно сбрасывает данные трассировки, когда программа аварийно завершает работу из-за неперехваченной паники. Это означает, что более полные данные трассировки будут доступны в трассировке, если программа аварийно завершает работу во время активной трассировки.

slices

Функция Repeat возвращает новый срез, который повторяет предоставленный срез указанное количество раз.

sync

Метод Map.Clear удаляет все записи, в результате чего получается пустая карта. Он аналогичен clear.

sync/atomic

Новые операторы And и Or применяют побитовое И или ИЛИ к заданным входным данным, возвращая старое значение.

syscall

Пакет syscall теперь определяет WSAENOPROTOOPT в Windows.

Функция GetsockoptInt теперь поддерживается в Windows.

testing/fstest

TestFS теперь возвращает структурированную ошибку, которую можно развернуть (с помощью метода Unwrap() []error). Это позволяет проверять ошибки с помощью error.Is или error.As.

text/template

Теперь шаблоны поддерживают новое действие "else with", что снижает сложность шаблона в некоторых случаях использования.

time

Parse и ParseInLocation теперь возвращают ошибку, если смещение часового пояса выходит за пределы диапазона.

unicode/utf16

Функция RuneLen возвращает количество 16-битных слов в кодировке UTF-16 руны. Она возвращает -1, если руна не является допустимым значением для кодировки в UTF-16.

Порты

Darwin

Как было объявлено в примечаниях к выпуску Go 1.22, Go 1.23 требует macOS 11 Big Sur или более поздней версии; поддержка предыдущих версий прекращена.

Linux

Go 1.23 — последний релиз, требующий версию ядра Linux 2.6.32 или более позднюю. Go 1.24 потребует версию ядра Linux 3.17 или более позднюю, за исключением того, что системы под управлением 3.10 или более поздней версии будут по-прежнему поддерживаться, если ядро было исправлено для поддержки системного вызова getrandom.

OpenBSD

Go 1.23 добавляет экспериментальную поддержку OpenBSD на 64-битном RISC-V (GOOS=openbsd, GOARCH=riscv64).

ARM64

Go 1.23 вводит новую переменную среды GOARM64, которая указывает минимальную целевую версию архитектуры ARM64 во время компиляции. Допустимые значения: v8.{0-9} и v9.{0-5}. За этим может следовать параметр, указывающий расширения, реализованные целевым оборудованием. Допустимые параметры: ,lse и ,crypto.

Переменная среды GOARM64 по умолчанию — v8.0.

RISC-V

В Go 1.23 представлена новая переменная среды GORISCV64, которая выбирает профиль приложения пользовательского режима RISC-V для компиляции. Допустимые значения: rva20u64 и rva22u64.

Переменная среды GORISCV64 по умолчанию — rva20u64.

Wasm

Скрипт go_wasip1_wasm_exec в GOROOT/misc/wasm прекратил поддержку версий wasmtime < 14.0.0.


Читайте также:


пятница, 17 мая 2024 г.

Релиз Go 1.22

Релиз Go 1.22, выходит через шесть месяцев после Go 1.21. Большинство изменений касается реализации цепочки инструментов, среды выполнения и библиотек. Как всегда, в релизе сохраняется обещание совместимости с Go 1. Ожидается, что почти все программы Go будут продолжать компилироваться и работать, как и раньше.

Изменения в языке

Go 1.22 вносит два изменения в циклы for.

  • Раньше переменные, объявленные в цикле for, создавались один раз и обновлялись на каждой итерации. В Go 1.22 каждая итерация цикла создает новые переменные, чтобы избежать случайных ошибок совместного использования. Инструменты поддержки перехода, описанные в предложении, продолжают работать так же, как и в Go 1.21.
  • Циклы for теперь могут охватывать целые числа. Например:

    package main
    
    import "fmt"
    
    func main() {
      for i := range 10 {
        fmt.Println(10 - i)
      }
      fmt.Println("go1.22 has lift-off!")
    }
    

Go 1.22 включает предварительный просмотр изменения языка, которое рассматриваются для будущей версии Go: итераторы диапазона по функции. Сборка с использованием GOEXPERIMENT=rangefunc включает эту функцию.

Инструменты

Команда go

Команды в рабочих областях теперь могут использовать каталог vendor, содержащий зависимости рабочей области. Каталог создается go work vendor и используется командами сборки, когда для флага -mod установлено значение vendor, что является значением по умолчанию, когда присутствует каталог vendor рабочей области.

Обратите внимание, что содержимое каталога vendor для рабочей области отличается от содержимого каталога отдельного модуля: если каталог в корне рабочей области также содержит один из модулей в рабочей области, его каталог vendor может содержать зависимости либо рабочей области, либо модуль, но не оба.

go get больше не поддерживается за пределами модуля в устаревшем режиме GOPATH (то есть с GO111MODULE=off). Другие команды сборки, такие как go build и go test, будут продолжать работать в устаревших программах GOPATH в течение неопределенного времени.

go mod init больше не пытается импортировать требования к модулям из файлов конфигурации для других инструментов поставщиков (таких как Gopkg.lock).

go test -cover теперь печатает сводные данные о покрытии для покрываемых пакетов, у которых нет собственных тестовых файлов. До версии Go 1.22 при запуске go test -cover для такого пакета выдавалось сообщение
? mymod/mypack [no test files]
и теперь с Go 1.22 функции в пакете считаются непокрытыми:
mymod/mypack coverage: 0.0% of statements

? mymod/mypack [no test files]

Обратите внимание: если пакет вообще не содержит исполняемого кода, мы не можем сообщить о значимом проценте покрытия; для таких пакетов инструмент go будет продолжать сообщать об отсутствии тестовых файлов.

Команды go build, вызывающие компоновщик, теперь выдают ошибку, если будет использоваться внешний (C) компоновщик, но cgo не включен. (Среде выполнения Go требуется поддержка cgo, чтобы гарантировать ее совместимость с любыми дополнительными библиотеками, добавленными компоновщиком C.)

Trace

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

Эти улучшения применимы только для просмотра трассировок, созданных программами, созданными на Go 1.22 или новее. В будущем релизе некоторые из этих улучшений будут внесены в трассировки, создаваемые старой версией Go.

Go Vet

Ссылки на переменные цикла

Поведение инструмента vet изменилось, чтобы соответствовать новой семантике переменных цикла в Go 1.22. При анализе файла, для которого требуется Go 1.22 или новее (из-за файла go.mod или ограничения сборки для каждого файла), vet больше не сообщает о ссылках на переменные цикла внутри функционального литерала, которые могут пережить итерацию цикла. В Go 1.22 переменные цикла создаются заново для каждой итерации, поэтому такие ссылки больше не подвергаются риску использования переменной после ее обновления циклом.

Новые предупреждения об отсутствующих значениях после append

Инструмент vet теперь сообщает о вызовах append, которые не передают никаких значений для добавления к срезу, например slice = append(slice). Такое выражение не имеет никакого эффекта, и опыт показывает, что это почти всегда ошибка.

Новые предупреждения об отсрочке (defer) time.Since.

Инструмент vet теперь сообщает о неотложенном вызове time.Since(t) внутри оператора defer. Это эквивалентно вызову time.Now().Sub(t) перед оператором defer, а не при вызове отложенной функции. Почти во всех случаях правильный код требует отсрочки вызова time.Since. Например:

t := time.Now()
defer log.Println(time.Since(t)) // неотложенный вызов time.Since
tmp := time.Since(t); defer log.Println(tmp) // эквивалентно предыдущему defer

defer func() {
  log.Println(time.Since(t)) // корректно отложенный вызов time.Since
}()

Новые предупреждения о несовпадающих парах ключ-значение в вызовах log/slog.

Инструмент vet теперь сообщает о недопустимых аргументах при вызовах функций и методов в пакете структурированного журналирования log/slog, который принимает чередующиеся пары ключ/значение. Он сообщает о вызовах, в которых аргумент в ключевой позиции не является ни строкой, ни slog.Attr, и где в конечном ключе отсутствует свое значение.

Среда времени исполнения (runtime)

Среда выполнения теперь хранит метаданные сборки мусора на основе типов ближе к каждому объекту кучи, улучшая производительность ЦП (задержку или пропускную способность) программ Go на 1–3%. Это изменение также снижает затраты памяти большинства программ Go примерно на 1% за счет дедупликации избыточных метаданных. В некоторых программах улучшение может быть меньшим, поскольку это изменение корректирует границы класса размера распределителя памяти, поэтому некоторые объекты могут быть перемещены на класс размера выше.

Следствием этого изменения является то, что адреса некоторых объектов, которые раньше всегда были выровнены по границе 16 байт (или выше), теперь будут выровнены только по границе 8 байт. Некоторые программы, использующие инструкции ассемблера, требующие, чтобы адреса памяти были выровнены по размеру более 8 байт и полагаются на предыдущее поведение выравнивания распределителя памяти, могут выйти из строя, но ожидается, что такие программы будут редкими. Такие программы могут быть созданы с использованием GOEXPERIMENT=noallocheaders, чтобы вернуться к старому макету метаданных и восстановить предыдущее поведение выравнивания, но владельцам пакетов следует обновить свой ассемблерный код, чтобы избежать предположения о выравнивании, поскольку этот обходной путь будет удален в будущем релизе.

В порте windows/amd64 программы, связывающие или загружающие библиотеки Go, созданные с помощью -buildmode=c-archive или -buildmode=c-shared, теперь могут использовать функцию SetUnhandledExceptionFilter Win32 для перехвата исключений, не обрабатываемых средой выполнения Go. Обратите внимание, что это уже поддерживалось в порте Windows/386.

Компилятор

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

Компилятор теперь чередует девиртуализацию и встраивание, поэтому вызовы методов интерфейса лучше оптимизированы.

Go 1.22 также включает предварительную версию расширенной реализации фазы встраивания компилятора, которая использует эвристику для повышения встраиваемости на местах вызовов, которые считаются "важными" (например, в циклах), и препятствует встраиванию на местах вызовов, которые считаются "неважными" (например, на пути паники). Сборка с использованием GOEXPERIMENT=newinliner позволяет использовать новую эвристику места вызова.

Линкер

Флаги -s и -w компоновщика теперь ведут себя более согласованно на всех платформах. Флаг -w подавляет генерацию отладочной информации DWARF. Флаг -s подавляет создание таблицы символов. Флаг -s также подразумевает флаг -w, который можно отменить с помощью -w=0. То есть -s -w=0 создаст двоичный файл с отладочной информацией DWARF, но без таблицы символов.

На платформах ELF флаг компоновщика -B теперь принимает специальную форму: с -B gobuildid компоновщик будет генерировать идентификатор сборки GNU (примечание ELF NT_GNU_BUILD_ID), полученный из идентификатора сборки Go.

В Windows при сборке с параметром -linkmode=internal компоновщик теперь сохраняет информацию SEH из объектных файлов C, копируя разделы .pdata и .xdata в окончательный двоичный файл. Это помогает при отладке и профилировании двоичных файлов с использованием собственных инструментов, таких как WinDbg. Обратите внимание, что до сих пор обработчики исключений SEH функций C не учитывались, поэтому это изменение может привести к тому, что некоторые программы будут вести себя по-другому. -linkmode=external это изменение не затрагивает, поскольку внешние компоновщики уже сохраняют информацию SEH.

Бутстрап

Как упоминалось в примечаниях к релизу Go 1.20, Go 1.22 теперь требует финальной версии Go 1.20 или новее для начальной загрузки. Ожидается, что Go 1.24 потребует финальной версии Go 1.22 или более поздней версии для начальной загрузки.

Основная библиотека

Новый пакет math/rand/v2

Go 1.22 включает первый пакет "v2" стандартной библиотеки — math/rand/v2. Наиболее важные изменения:

  • Метод Read, устаревший в math/rand, не был перенесен в math/rand/v2. (Он остается доступным в math/rand.) Подавляющее большинство вызовов Read должны использовать вместо этого Read crypto/rand. В противном случае можно создать пользовательский Read с использованием метода Uint64.
  • Глобальный генератор, к которому обращаются функции верхнего уровня, заполняется безусловно случайным образом. Поскольку API не гарантирует фиксированной последовательности результатов, теперь возможны такие оптимизации, как состояния генератора случайных чисел для каждого потока.
  • Интерфейс Source теперь имеет единственный метод Uint64; нет интерфейса Source64.
  • Многие методы теперь используют более быстрые алгоритмы, которые невозможно было применить в math/rand, поскольку они изменили выходные потоки.
  • Функции и методы верхнего уровня Intn, Int31, Int31n, Int63 и Int64n из math/rand в math/rand/v2 пишутся более идиоматично: IntN, Int32, Int32N, Int64 и Int64N. Также появились новые функции и методы верхнего уровня Uint32, Uint32N, Uint64, Uint64N, Uint и UintN.
  • Новая универсальная функция N похожа на Int64N или Uint64N, но работает для любого целочисленного типа. Например, случайная длительность от 0 до 5 минут равна rand.N(5*time.Minute).
  • Генератор LFSR Mitchell & Reeds, предоставленный math/rand Source, был заменен двумя более современными источниками псевдослучайного генератора: ChaCha8 и PCG. ChaCha8 — это новый, криптостойкий генератор случайных чисел, по эффективности примерно аналогичный PCG. ChaCha8 — это алгоритм, используемый для функций верхнего уровня в math/rand/v2. Начиная с Go 1.22, функции верхнего уровня math/rand (если они не заданы явно) и среда выполнения Go также используют ChaCha8 для случайности.

Планируется включить инструмент миграции API в будущую версию, скорее всего, в Go 1.23.

Новый пакет go/version

Новый пакет go/version реализует функции для проверки и сравнения строк версии Go.

Улучшенные шаблоны маршрутизации

HTTP-маршрутизация в стандартной библиотеке стала более выразительной. Шаблоны, используемые net/http.ServeMux, были улучшены и теперь принимают методы и подстановочные знаки.

Регистрация обработчика с помощью метода, например "POST/items/create", ограничивает вызовы обработчика запросами с данным методом. Шаблон с методом имеет приоритет над совпадающим шаблоном без него. В частном случае регистрация обработчика с помощью "GET" также регистрирует его с помощью "HEAD".

Подстановочные знаки в шаблонах, например /items/{id}, соответствуют сегментам URL-пути. Доступ к фактическому значению сегмента можно получить, вызвав метод Request.PathValue. Подстановочный знак, оканчивающийся на "...", например /files/{path...}, должен находиться в конце шаблона и соответствовать всем остальным сегментам.

Шаблон, оканчивающийся на "/", как всегда, соответствует всем путям, в которых он есть в качестве префикса. Чтобы точно соответствовать шаблону, включая косую черту, завершите его {$}, как в /exact/match/{$}.

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

Это изменение нарушает обратную совместимость в некоторых аспектах, некоторые из которых очевидны — шаблоны с "{" и "}" ведут себя по-другому, а некоторые — в меньшей степени — улучшена обработка экранированных путей. Изменение контролируется полем GODEBUG с именем httpmuxgo121. Установите httpmuxgo121=1, чтобы восстановить старое поведение.

Небольшие изменения в библиотеке

Как всегда, в библиотеку внесены различные незначительные изменения и обновления, сделанные с учетом обеспечения совместимости с Go 1. Существуют также различные улучшения производительности, которые здесь не перечислены.

archive/tar

Новый метод Writer.AddFS добавляет в архив все файлы из fs.FS.

archive/zip

Новый метод Writer.AddFS добавляет в архив все файлы из fs.FS.

bufio

Когда SplitFunc возвращает ErrFinalToken с нулевым токеном, Scanner немедленно останавливается. Раньше перед остановкой он сообщал об окончательном пустом токене, что обычно было нежелательно. Вызывающие, которые хотят сообщить об окончательном пустом токене, могут сделать это, вернув []byte{}, а не nil.

cmp

Новая функция Or возвращает первое значение в последовательности, которое не является нулевым значением.

crypto/tls

ConnectionState.ExportKeyingMaterial теперь будет возвращать ошибку, если не используется TLS 1.3 или расширение Extended_master_secret не поддерживается как сервером, так и клиентом. crypto/tls поддерживает это расширение начиная с Go 1.20. Это можно отключить с помощью параметра tlsunsafeekm=1 GODEBUG.

По умолчанию минимальной версией, предлагаемой серверами crypto/tls, теперь является TLS 1.2, если она не указана в config.MinimumVersion, что соответствует поведению клиентов crypto/tls. Это изменение можно отменить с помощью параметра tls10server=1 GODEBUG.

По умолчанию наборы шифров без поддержки ECDHE больше не предлагаются ни клиентами, ни серверами во время рукопожатий до TLS 1.3. Это изменение можно отменить с помощью настройки tlsrsakex=1 GODEBUG.

crypto/x509

Новый метод CertPool.AddCertWithConstraint можно использовать для добавления настраиваемых ограничений к корневым сертификатам, которые будут применяться во время построения цепочки.

В Android корневые сертификаты теперь будут загружаться из /data/misc/keychain/certs-added, а также из /system/etc/security/cacerts.

Новый тип OID поддерживает идентификаторы объектов ASN.1 с отдельными компонентами длиной более 31 бита. Новое поле, использующее этот тип, Policies, добавляется в структуру сертификата и теперь заполняется во время анализа. Любые OID, которые невозможно представить с помощью asn1.ObjectIdentifier, появятся в политиках, но не в старом поле PolicyIdentifiers. При вызове CreateCertificate поле Policies игнорируется, а политики берутся из поля PolicyIdentifiers. Использование параметра x509usepolicies=1 GODEBUG инвертирует это, заполняя политики сертификатов из поля Policies и игнорируя поле PolicyIdentifiers. Возможно изменение значения по умолчанию для x509usepolicies в Go 1.23, которое сделает Policies полем по умолчанию для маршалинга.

database/sql

Новый тип Null[T] предоставляет возможность сканирования столбцов, допускающих значение NULL, на предмет любых типов столбцов.

debug/elf

Константа R_MIPS_PC32 определена для использования с системами MIPS64.

Дополнительные константы R_LARCH_* определены для использования с системами LoongArch.

encoding

Новые методы AppendEncode и AppendDecode, добавленные к каждому из типов кодирования в пакетах  encoding/base32, encoding/base64 и encoding/hex, упрощают кодирование и декодирование из и в байтовые срезы, заботясь об управлении буфером байтовых срезов.

Методы base32.Encoding.WithPadding и base64.Encoding.WithPadding теперь вызывают панику, если аргумент заполнения имеет отрицательное значение, отличное от NoPadding.

encoding/json

Функции маршалинга и кодирования теперь экранируют символы '\b' и '\f' как \b и \f вместо \u0008 и \u000c.

go/ast

Следующие объявления, связанные с разрешением синтаксических идентификаторов, теперь устарели: Ident.Obj, Object, Scope, File.Scope, File.Unresolved, Importer, Package, NewPackage. В общем, идентификаторы не могут быть точно определены без информации о типе. Рассмотрим, например, идентификатор K в T{K: ""}: это может быть имя локальной переменной, если T является типом карты, или именем поля, если T является типом структуры. Новые программы должны использовать пакет go/types для разрешения идентификаторов.

Новая функция ast.Unparen удаляет из выражения все закрывающие круглые скобки.

go/types

Новый тип Alias представляет псевдонимы типов. Раньше псевдонимы типов не представлялись явно, поэтому ссылка на псевдоним типа была эквивалентна указанию псевдонима типа, и имя псевдонима терялось. Новое представление сохраняет промежуточный псевдоним. Это позволяет улучшить отчеты об ошибках (можно сообщить имя псевдонима типа) и позволяет лучше обрабатывать объявления циклических типов, включающие псевдонимы типов. В будущем выпуске типы псевдонимов также будут содержать информацию о параметрах типа. Новая функция Unalias возвращает фактический тип, обозначенный типом Alias (или любым другим типом, если на то пошло).

Поскольку типы псевдонимов могут нарушить работу существующих переключателей типов, которые не умеют их проверять, эта функциональность контролируется полем GODEBUG с именем gotypesalias. Если gotypesalias=0, все работает как прежде, и типы псевдонимов никогда не создаются. Если gotypesalias=1, создаются типы псевдонимов, и клиенты должны их ожидать. По умолчанию используется gotypesalias=0. В будущем релизе значение по умолчанию будет изменено на gotypesalias=1. Клиентам go/types настоятельно рекомендуется как можно скорее скорректировать свой код для работы с gotypesalias=1, чтобы устранить проблемы на раннем этапе.

Структура Info теперь экспортирует карту FileVersions, которая предоставляет информацию о версии Go для каждого файла.

Новый вспомогательный метод PkgNameOf возвращает имя локального пакета для данного объявления импорта.

Реализация SizesFor была скорректирована для вычисления тех же размеров типов, что и компилятор, когда аргументом компилятора SizesFor является "gc". Реализация Sizes по умолчанию, используемая средством проверки типов, теперь имеет вид Types.SizesFor("gc", "amd64").

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

html/template

Литералы шаблонов Javascript теперь могут содержать действия шаблона Go, а анализ шаблона, содержащего такие действия, больше не будет возвращать ErrJSTemplate. Аналогично, параметр jstmpllitinterp в GODEBUG больше не имеет никакого эффекта.

io

Новый метод SectionReader.Outer возвращает ReaderAt, смещение и размер, переданные в NewSectionReader.

log/slog

Новая функция SetLogLoggerLevel контролирует уровень моста между пакетами `slog` и `log`. Он устанавливает минимальный уровень для вызовов функций ведения журнала `slog` верхнего уровня, а также устанавливает уровень для вызовов `log.Logger`, которые проходят через `slog`.

math/big

Новый метод Rat.FloatPrec вычисляет количество дробных десятичных цифр, необходимых для точного представления рационального числа в виде числа с плавающей запятой, а также определяет, возможно ли вообще точное десятичное представление.

net

Когда io.Copy копирует из TCPConn в UnixConn, он теперь будет использовать системный вызов Linux splice(2), если это возможно, используя новый метод TCPConn.WriteTo.

DNS-резольвер Go, используемый при сборке с "-tags=netgo", теперь ищет соответствующее имя в файле хостов Windows, расположенном по адресу %SystemRoot%\System32\drivers\etc\hosts, перед выполнением DNS-запроса.

net/http

Новые функции ServeFileFS, FileServerFS и NewFileTransportFS являются версиями существующих ServeFile, FileServer и NewFileTransport, работающих на fs.FS.

HTTP-сервер и клиент теперь отклоняют запросы и ответы, содержащие недопустимый пустой заголовок Content-Length. Предыдущее поведение можно восстановить, установив поле GODEBUG httplaxcontentlength=1.

Новый метод Request.PathValue возвращает значения подстановочных знаков пути из запроса, а новый метод Request.SetPathValue устанавливает значения подстановочных знаков пути в запросе.

net/http/cgi

При выполнении процесса CGI переменной PATH_INFO теперь всегда присваивается пустая строка или значение, начинающееся с символа /, как того требует RFC 3875. Ранее для некоторых комбинаций Handler.Root и URL-адреса запроса было возможно нарушить это требование.

net/netip

Новый метод AddrPort.Compare сравнивает два AddrPort.

os

В Windows функция Stat теперь следует за всеми точками повторной обработки, которые ссылаются на другой именованный объект в системе. Раньше он следовал только за точками повторной обработки IO_REPARSE_TAG_SYMLINK и IO_REPARSE_TAG_MOUNT_POINT.

В Windows передача O_SYNC в OpenFile теперь приводит к тому, что операции записи передаются непосредственно на диск, что эквивалентно O_SYNC на платформах Unix.

В Windows функции ReadDir, File.ReadDir, File.Readdir и File.Readdirnames теперь считывают записи каталога в пакетном режиме, чтобы сократить количество системных вызовов, повышая производительность до 30%.

Когда io.Copy копирует из файла в net.UnixConn, он теперь будет использовать системный вызов Linux sendfile(2), если это возможно, используя новый метод File.WriteTo.

os/exec

В Windows LookPath теперь игнорирует пустые записи в %PATH% и возвращает ErrNotFound (вместо ErrNotExist), если не найдено расширение исполняемого файла для разрешения однозначного имени.

В Windows Command и Cmd.Start больше не вызывают LookPath, если путь к исполняемому файлу уже является абсолютным и имеет расширение исполняемого файла. Кроме того, Cmd.Start больше не записывает разрешенное расширение обратно в поле Path, поэтому теперь можно безопасно вызывать метод String одновременно с вызовом Start.

reflect

Метод Value.IsZero теперь возвращает true для числа с плавающей запятой или комплексного отрицательного нуля, а также возвращает true для значения структуры, если пустое поле (поле с именем _) каким-то образом имеет ненулевое значение. Эти изменения делают IsZero совместимым со сравнением значения с нулем с помощью оператора языка ==.

Функция PtrTo устарела в пользу PointerTo.

Новая функция TypeFor возвращает Type, который представляет аргумент типа T. Раньше, чтобы получить значение Reflect.Type для типа, нужно было использовать Reflect.TypeOf((*T)(nil)).Elem(). Теперь это можно записать как reflect.TypeFor[T]().

runtime/metrics

Четыре новых показателя гистограммы /sched/pauses/stopping/gc:seconds, /sched/pauses/stopping/other:seconds, /sched/pauses/total/gc:seconds и /sched/pauses/total/other:seconds предоставляют дополнительные подробности о паузах, связанных с остановкой мира. Метрики "остановки" сообщают о времени, прошедшем от принятия решения об остановке мира до остановки всех горутин. "Общие" показатели сообщают о времени, прошедшем от принятия решения остановить мир до его повторного запуска.

Метрика /gc/pauses:seconds устарела, поскольку она эквивалентна новой метрике /sched/pauses/total/gc:seconds.

/sync/mutex/wait/total:seconds теперь включают в себя конфликты по внутренним блокировкам времени выполнения в дополнение к sync.Mutex и sync.RWMutex.

runtime/pprof

Профили мьютексов теперь масштабируют конкуренцию по количеству горутин, заблокированных во мьютексе. Это обеспечивает более точное представление о степени, в которой мьютекс является узким местом в программе Go. Например, если 100 горутин заблокированы мьютексом на 10 миллисекунд, профиль мьютекса теперь будет записывать задержку в 1 секунду вместо задержки в 10 миллисекунд.

Профили мьютексов теперь также включают конкуренцию за внутренние блокировки во время выполнения в дополнение к sync.Mutex и sync.RWMutex. Конфликт по внутренним блокировкам во время выполнения всегда сообщается во время runtime._LostContendedRuntimeLock. В будущих версиях в этих случаях будут добавлены полные трассировки стека.

Профили ЦП на платформах Darwin теперь содержат карту памяти процесса, что позволяет просматривать дизассемблирование в инструменте pprof.

runtime/trace

В этом выпуске трассировщик выполнения был полностью переработан, что решило несколько давних проблем и открыло путь для новых вариантов использования трассировки выполнения.

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

Чтобы разработчики Go могли воспользоваться этими улучшениями, по адресу golang.org/x/exp/trace доступен экспериментальный пакет для чтения трассировки. Обратите внимание, что этот пакет работает только с трассировками, созданными программами, созданными на данный момент с помощью Go 1.22.

Если у вас возникнут какие-либо проблемы с новой реализацией трассировщика выполнения, вы можете вернуться к старой реализации, создав программу Go с GOEXPERIMENT=noexectracer2. Если да, сообщите о проблеме, иначе эта опция будет удалена в будущем релизе.

slices

Новая функция Concat объединяет несколько срезов.

Функции, уменьшающие размер среза (Delete, DeleteFunc, Compact, CompactFunc и Replace), теперь обнуляют элементы между новой длиной и старой длиной.

Команда Insert теперь всегда вызывает панику, если аргумент i выходит за пределы допустимого диапазона. Раньше в этой ситуации не паниковало, если не было элементов для вставки.

syscall

Пакет системных вызовов был заморожен начиная с Go 1.4 и помечен как устаревший в Go 1.11, из-за чего многие редакторы предупреждают о любом использовании пакета. Однако для некоторых неустаревших функций требуется использование пакета syscall, например поля os/exec.Cmd.SysProcAttr. Чтобы избежать ненужных жалоб на такой код, пакет syscall больше не помечается как устаревший. Пакет остается замороженным для большинства новых функций, и в новом коде по-прежнему рекомендуется использовать golang.org/x/sys/unix или golang.org/x/sys/windows, где это возможно.

В Linux новое поле SysProcAttr.PidFD позволяет получить PID FD при запуске дочернего процесса через StartProcess или os/exec.

В Windows передача O_SYNC в Open теперь приводит к тому, что операции записи передаются непосредственно на диск, что эквивалентно O_SYNC на платформах Unix.

testing/slogtest

Новая функция Run использует подтесты для запуска тестовых случаев, обеспечивая более детальный контроль.

Порты

Darwin

В macOS на 64-битной архитектуре x86 (порт darwin/amd64) набор инструментов Go теперь по умолчанию генерирует позиционно-независимые исполняемые файлы (PIE). Двоичные файлы, отличные от PIE, можно создать, указав флаг сборки -buildmode=exe. В 64-битной macOS на базе ARM (порт darwin/arm64) набор инструментов Go уже генерирует PIE по умолчанию.

Go 1.22 — последний релиз, который будет работать на macOS 10.15 Catalina. Для Go 1.23 потребуется macOS 11 Big Sur или более поздняя версия.

Arm

Переменная среды GOARM теперь позволяет вам выбирать, использовать ли программную или аппаратную плавающую запятую. Раньше допустимыми значениями GOARM были 5, 6 или 7. Теперь за этими же значениями можно опционально следовать ,softfloat или ,hardfloat для выбора реализации с плавающей запятой.

Эта новая опция по умолчанию имеет мягкое плавание для версии 5 и жесткое плавание для версий 6 и 7.

Loong64

Порт loong64 теперь поддерживает передачу аргументов функции и результатов с использованием регистров.

Порт linux/loong64 теперь поддерживает очистку адресов, очистку памяти, перемещение компоновщика нового стиля и режим сборки плагинов.

OpenBSD

В Go 1.22 добавлен экспериментальный порт OpenBSD на 64-битном PowerPC с прямым порядком байтов (openbsd/ppc64).


Читайте также:


вторник, 29 августа 2023 г.

Релиз Go 1.21

Релиз Go, версия 1.21, выходит через шесть месяцев после Go 1.20. Большинство его изменений касаются реализации цепочки инструментов, среды выполнения и библиотек. Как всегда, выпуск поддерживает обещание совместимости Go 1; на самом деле Go 1.21 улучшает это обещание. Ожидается, что почти все программы Go продолжат компилироваться и работать, как и раньше.

В Go 1.21 внесено небольшое изменение в нумерацию релизов. В прошлом использовали Go 1.N для обозначения как общей языковой версии Go, так и семейства релизов, а также первого релиза в этом семействе. Начиная с версии Go 1.21, первый релиз теперь называется Go 1.N.0. В этот раз выпускается как язык Go 1.21, так и его первоначальная реализация, версию Go 1.21.0. Эти примечания относятся к "Go 1.21"; такие инструменты, как go version, будут сообщать "go1.21.0" (пока вы не обновитесь до версии Go 1.21.1).

Изменения в языке

Go 1.21 добавляет в язык три новых встроенных модуля.

  • Новые функции min и max вычисляют наименьшее (или наибольшее для max) значение фиксированного числа заданных аргументов.
  • Новая функция clear удаляет все элементы с карты или обнуляет все элементы среза.

Порядок инициализации пакетов теперь указан более точно. Новый алгоритм таков:

  • Отсортируйте все пакеты по пути импорта.
  • Повторяйте, пока список пакетов не станет пустым:
    • Найдите в списке первый пакет, для которого все импорты уже инициализированы.
    • Инициализируйте этот пакет и удалите его из списка.

Это может изменить поведение некоторых программ, которые полагаются на определенный порядок инициализации, не выраженный явным импортом. Поведение таких программ не было четко определено спецификацией в прошлых релизах. Новое правило дает однозначное определение.

Внесено множество улучшений, повышающих мощность и точность вывода типов.

  • Функция (возможно, частично созданная универсальная) теперь может быть вызвана с аргументами, которые сами являются (возможно, частично созданными) универсальными функциями. Компилятор попытается вывести отсутствующие аргументы типа вызываемого объекта (как и раньше) и для каждого аргумента, который является универсальной функцией, экземпляр которой не полностью создан, его отсутствующие аргументы типа (новые). Типичными вариантами использования являются вызовы универсальных функций, работающих с контейнерами (например, slices.IndexFunc), где аргумент функции также может быть универсальным, а аргумент типа вызываемой функции и ее аргументы выводятся из типа контейнера. В более общем смысле универсальную функцию теперь можно использовать без явного создания экземпляра, когда она присваивается переменной или возвращается как значение результата, если аргументы типа можно вывести из присваивания.
  • Вывод типа теперь также учитывает методы, когда значение присваивается интерфейсу: аргументы типа для параметров типа, используемых в сигнатурах методов, могут быть выведены из соответствующих типов параметров соответствующих методов.
  • Точно так же, поскольку аргумент типа должен реализовывать все методы соответствующего ограничения, методы аргумента типа и ограничения совпадают, что может привести к выводу дополнительных аргументов типа.
  • Если несколько нетипизированных постоянных аргументов разных типов (таких как нетипизированное целое число и нетипизированная константа с плавающей запятой) передаются параметрам с одним и тем же (не указанным иным образом) типом параметра типа вместо ошибки, теперь вывод типа определяет тип, используя тот же подход, что и у оператора с нетипизированными постоянными операндами. Это изменение приводит типы, выведенные из нетипизированных константных аргументов, в соответствие с типами константных выражений.
  • Вывод типа теперь является точным при сопоставлении соответствующих типов в присваиваниях: типы компонентов (такие как элементы срезов или типы параметров в сигнатурах функций) должны быть идентичными (с учетом подходящих аргументов типа) для сопоставления, иначе вывод завершится ошибкой. Это изменение создает более точные сообщения об ошибках: если в прошлом вывод типа мог завершиться неправильно и привести к недопустимому присвоению, теперь компилятор сообщает об ошибке вывода, если два типа не могут совпасть.

В более общем плане описание вывода типов в спецификации языка было уточнено. Вместе все эти изменения делают вывод типов более мощным, а ошибки вывода менее неожиданными.

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

Go 1.21 теперь определяет, что если горутина находится в состоянии паники, а функция recovery была вызвана непосредственно отложенной функцией, возвращаемое значение recovery гарантированно не равно нулю. Чтобы гарантировать это, вызов panic со значением интерфейса nil (или нетипизированным nil) вызывает панику во время выполнения типа *runtime.PanicNilError.

Для поддержки программ, написанных для более старых версий Go, nil panic можно повторно включить, установив GODEBUG=panicnil=1. Этот параметр включается автоматически при компиляции программы, основной пакет которой находится в модуле, объявляющем go 1.20 или более ранней версии.

Инструменты

Go 1.21 добавляет улучшенную поддержку обратной и прямой совместимости в цепочке инструментов Go.

Чтобы улучшить обратную совместимость, Go 1.21 формализует использование Go переменной среды GODEBUG для управления поведением по умолчанию для изменений, которые не являются критическими в соответствии с политикой совместимости, но, тем не менее, могут привести к нарушению работы существующих программ. (Например, программы, зависящие от ошибочного поведения, могут сломаться, когда ошибка будет исправлена, но исправления ошибок не считаются критическими изменениями.) Когда Go должен внести такое изменение поведения, теперь он выбирает между старым и новым поведением на основе go в файле go.work рабочей области или в файле go.mod основного модуля. При обновлении до новой цепочки инструментов Go, но с сохранением исходной (старой) версии Go для строки go сохраняется поведение старой цепочки инструментов. Благодаря такой поддержке совместимости последняя цепочка инструментов Go всегда должна быть лучшей и наиболее безопасной реализацией старой версии Go.

Для улучшения совместимости Go 1.21 теперь считывает строку go в файле go.work или go.mod как строгое минимальное требование: go 1.21.0 означает, что рабочее пространство или модуль нельзя использовать с Go 1.20 или Go 1.21rc1. Это позволяет проектам, которые зависят от исправлений, сделанных в более поздних версиях Go, гарантировать, что они не используются с более ранними версиями. Это также дает более качественные отчеты об ошибках для проектов, использующих новые функции Go: когда проблема заключается в том, что требуется более новая версия Go, об этой проблеме сообщается четко, вместо того, чтобы пытаться построить код и печатать ошибки о неразрешенных импортах или синтаксических ошибках.

Чтобы упростить управление этими новыми более строгими требованиями к версии, команда go теперь может вызывать не только цепочку инструментов, входящую в ее собственный релиз, но и другие версии цепочки инструментов Go, найденные в PATH или загруженные по запросу. Если строка go.mod или go.work объявляет минимальные требования к более новой версии Go, команда go автоматически найдет и запустит эту версию. Новая директива цепочки инструментов устанавливает рекомендуемый минимальный набор инструментов для использования, который может быть новее, чем строгий минимум.

Команда go

Флаг сборки -pgo теперь по умолчанию имеет значение -pgo=auto, а ограничение на указание одного основного пакета в командной строке теперь снято. Если файл с именем default.pgo присутствует в каталоге основного пакета, команда go будет использовать его, чтобы включить оптимизацию на основе профиля для сборки соответствующей программы.

Флаг -C dir теперь должен быть первым флагом в командной строке при использовании.

Новая опция go test -fullpath печатает полные пути в сообщениях журнала тестирования, а не только базовые имена.

Флаг go test -c теперь поддерживает запись тестовых двоичных файлов для нескольких пакетов, каждый в pkg.test, где pkg — это имя пакета. Будет ошибкой, если более одного компилируемого тестового пакета имеют заданное имя пакета.

Флаг go test -o теперь принимает аргумент каталога, и в этом случае тестовые двоичные файлы записываются в этот каталог, а не в текущий каталог.

Cgo

В файлах, которые импортируют "C", набор инструментов Go теперь правильно сообщает об ошибках при попытках объявить методы Go для типов C.

Среда времени исполнения (Runtime)

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

На платформах Linux, которые поддерживают прозрачные огромные страницы (transparent huge pages), среда выполнения Go теперь более явно определяет, какие части кучи могут быть поддержаны огромными страницами. Это приводит к лучшему использованию памяти: для небольших куч должно использоваться меньше памяти (до 50 % в патологических случаях), тогда как для больших куч должно использоваться меньше испорченных огромных страниц для плотных частей кучи, что улучшает использование ЦП и задержку до 1%.

В результате внутренней настройки сборки мусора во время выполнения приложения могут сократить задержку хвоста приложения на 40% и небольшое снижение использования памяти. В некоторых приложениях также может наблюдаться небольшая потеря пропускной способности. Уменьшение использования памяти должно быть пропорционально потере пропускной способности, чтобы компромисс между пропускной способностью и памятью предыдущей версии можно было восстановить (с небольшим изменением задержки) путем небольшого увеличения GOGC и/или GOMEMLIMIT.

Вызовы из C в Go в потоках, созданных в C, требуют некоторой настройки для подготовки к выполнению Go. На платформах Unix эта настройка теперь сохраняется при нескольких вызовах из одного потока. Это значительно снижает накладные расходы на последующие вызовы C в Go с ~1–3 микросекунд на вызов до ~100–200 наносекунд на вызов.

Компилятор

Оптимизация на основе профиля (PGO, Profile-guide optimization), добавленная в качестве предварительной версии в Go 1.20, теперь готова для общего использования. PGO обеспечивает дополнительную оптимизацию кода, который определяется как "горячий" в соответствии с профилями производственных рабочих нагрузок. Как упоминалось в разделе команд Go, PGO включен по умолчанию для двоичных файлов, которые содержат профиль default.pgo в основном каталоге пакета. Улучшение производительности варьируется в зависимости от поведения приложения: в большинстве программ из репрезентативного набора программ Go наблюдается улучшение от 2 до 7% от включения PGO.

Сборки PGO теперь могут девиртуализировать вызовы некоторых методов интерфейса, добавляя конкретный вызов к наиболее распространенному вызываемому объекту. Это обеспечивает дальнейшую оптимизацию, например, встраивание вызываемого объекта.

Go 1.21 повышает скорость сборки до 6%, во многом благодаря сборке самого компилятора с помощью PGO.

Ассемблер

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

Улучшен верификатор, проверяющий неправильное использование R15 при динамической компоновке на amd64.

Компоновщик (Linker)

В windows/amd64 компоновщик (с помощью компилятора) теперь по умолчанию выдает данные размотки SEH, что улучшает интеграцию приложений Go с отладчиками Windows и другими инструментами.

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

Основная библиотека

Новый пакет log/slog

Новый пакет log/slog обеспечивает структурированное ведение журналов по уровням. Структурированное ведение журналов генерирует пары "ключ-значение", что обеспечивает быструю и точную обработку больших объемов данных журнала. Пакет поддерживает интеграцию с популярными инструментами и сервисами анализа журналов.

Новый пакет testing/slogtest

Новый пакет testing/slogtest может помочь проверить реализации slog.Handler.

Новый пакет slices

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

Новый пакет maps

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

Новый пакет cmp

Новый пакет cmp определяет ограничение типа Ordered и две новые универсальные функции Less и Compare, полезные для упорядоченных типов.

Небольшие изменения в библиотеке

Как всегда, в библиотеку внесены различные незначительные изменения и обновления, сделанные с учетом обеспечения совместимости с Go 1. Существуют также различные улучшения производительности, которые здесь не перечислены.

archive/tar

Реализация интерфейса io/fs.FileInfo, возвращаемого Header.FileInfo, теперь реализует метод String, который вызывает io/fs.FormatFileInfo.

archive/zip

Реализация интерфейса io/fs.FileInfo, возвращаемого FileHeader.FileInfo, теперь реализует метод String, который вызывает io/fs.FormatFileInfo.

Реализация интерфейса io/fs.DirEntry, возвращаемого методом io/fs.ReadDirFile.ReadDir io/fs.File, возвращаемого Reader.Open, теперь реализует метод String, который вызывает io/fs.FormatDirEntry.

bytes

Тип Buffer имеет два новых метода: Available и AvailableBuffer. Их можно использовать вместе с методом Write для добавления непосредственно в буфер.

context

Новая функция WithoutCancel возвращает копию контекста, которая не отменяется при отмене исходного контекста.

Новые функции WithDeadlineCause и WithTimeoutCause позволяют установить причину отмены контекста по истечении крайнего срока или таймера. Причину можно выяснить с помощью функции Cause.

Новая функция AfterFunc регистрирует функцию, которая будет запускаться после отмены контекста.

Оптимизация означает, что результаты вызова Background и TODO и преобразования их в общий тип можно считать равными. В предыдущих релизах они всегда были разными. Сравнение значений контекста на предмет равенства никогда не было четко определено, поэтому это не считается несовместимым изменением.

crypto/ecdsa

PublicKey.Equal и PrivateKey.Equal теперь выполняются за постоянное время.

crypto/elliptic

Все методы Curve, а также методы GenerateKey, Marshal и Unmarshal устарели. Для операций ECDH вместо этого следует использовать новый пакет crypto/ecdh. Для операций более низкого уровня используйте сторонние модули, такие как filippo.io/nistec.

crypto/rand

Пакет crypto/rand теперь использует системный вызов getrandom в NetBSD 10.0 и более поздних версиях.

crypto/rsa

Производительность частных операций RSA (расшифровка и подпись) теперь лучше, чем в Go 1.19 для GOARCH=amd64 и GOARCH=arm64. Производительность снижалась в Go 1.20.

Из-за добавления частных полей в PrecomputedValues PrivateKey.Precompute необходимо вызывать для оптимальной производительности даже при десериализации (например, из JSON) предварительно вычисленного закрытого ключа.

PublicKey.Equal и PrivateKey.Equal теперь выполняются за постоянное время.

Функция GenerateMultiPrimeKey и поле PrecomputedValues.CRTValues устарели. PrecomputedValues.CRTValues по-прежнему будет заполняться при вызове PrivateKey.Precompute, но значения не будут использоваться во время операций расшифровки.

crypto/sha256

Операции SHA-224 и SHA-256 теперь используют собственные инструкции, если они доступны при GOARCH=amd64, что обеспечивает повышение производительности примерно в 3–4 раза.

crypto/tls

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

Приложения теперь могут контролировать содержимое билетов сеанса.

  • Новый тип SessionState описывает возобновляемый сеанс.
  • Метод SessionState.Bytes и функция ParseSessionState сериализуют и десериализуют SessionState.
  • Перехватчики Config.WrapSession и Config.UnwrapSession преобразуют SessionState в билет и обратно на стороне сервера.
  • Методы Config.EncryptTicket и Config.DecryptTicket предоставляют реализацию WrapSession и UnwrapSession по умолчанию.
  • Метод ClientSessionState.ResumptionState и функция NewResumptionState могут использоваться реализацией ClientSessionCache для хранения и возобновления сеансов на стороне клиента.

Чтобы уменьшить вероятность использования билетов сеанса в качестве механизма отслеживания между соединениями, сервер теперь выдает новые билеты при каждом возобновлении (если они поддерживаются и не отключены), и билеты больше не содержат идентификатор ключа, который их зашифровал. Передача большого количества ключей в Conn.SetSessionTicketKeys может привести к заметному снижению производительности.

И клиенты, и серверы теперь реализуют расширение Extended Master Secret (RFC 7627). Устаревание ConnectionState.TLSUnique отменено и теперь установлено для возобновленных соединений, поддерживающих расширенный главный секрет.

Новый тип QUICConn обеспечивает поддержку реализаций QUIC, включая поддержку 0-RTT. Обратите внимание, что это само по себе не является реализацией QUIC, и 0-RTT по-прежнему не поддерживается в TLS.

Новая функция VersionName возвращает имя для номера версии TLS.

Были улучшены коды предупреждений TLS, отправляемые с сервера при ошибках аутентификации клиента. Раньше эти сбои всегда приводили к предупреждению о "плохом сертификате". Теперь при определенных сбоях будут использоваться более подходящие коды предупреждений, как определено в RFC 5246 и RFC 8446:

  • Для подключений TLS 1.3, если сервер настроен на требование проверки подлинности клиента с помощью RequireAnyClientCert или RequireAndVerifyClientCert, а клиент не предоставляет сертификат, сервер теперь вернет предупреждение "требуется сертификат".
  • Если клиент предоставляет сертификат, который не подписан набором доверенных центров сертификации, настроенных на сервере, сервер вернет предупреждение "неизвестный центр сертификации".
  • Если клиент предоставляет сертификат, срок действия которого истек или еще не действителен, сервер вернет предупреждение "сертификат с истекшим сроком действия".
  • Во всех других сценариях, связанных с ошибками аутентификации клиента, сервер по-прежнему возвращает "неверный сертификат".

crypto/x509

RevokedList.RevokedCertificates устарел и заменен новым полем RevokedCertificateEntries, которое является частью RevokedListEntry. RelocationListEntry содержит все поля в pkix.RevokedCertificate, а также код причины отзыва.

Ограничения имен теперь правильно применяются к нелистовым сертификатам, а не к сертификатам, в которых они выражены.

debug/elf

Новый метод File.DynValue можно использовать для получения числовых значений, перечисленных в данном динамическом теге.

Постоянные флаги, разрешенные в динамическом теге DT_FLAGS_1, теперь определяются с типом DynFlag1. Эти теги имеют имена, начинающиеся с DF_1.

Пакет теперь определяет константу COMPRESS_ZSTD.

Пакет теперь определяет константу R_PPC64_REL24_P9NOTOC.

debug/pe

Попытки чтения из раздела, содержащего неинициализированные данные, с помощью Section.Data или средства чтения, возвращаемого Section.Open, теперь возвращают ошибку.

embed

io/fs.File, возвращаемый FS.Open, теперь имеет метод ReadAt, реализующий io.ReaderAt.

Вызов FS.Open.Stat вернет тип, который теперь реализует метод String, вызывающий io/fs.FormatFileInfo.

errors

Новая ошибка ErrUnsupported предоставляет стандартизированный способ указать, что запрошенная операция не может быть выполнена, поскольку она не поддерживается. Например, вызов os.Link при использовании файловой системы, не поддерживающей жесткие ссылки.

flag

Новая функция BoolFunc и метод FlagSet.BoolFunc определяют флаг, который не требует аргумента, и вызывает функцию при использовании флага. Это похоже на Func, но с логическим флагом.

Определение флага (через Bool, BoolVar, Int, IntVar и т. д.) вызовет панику, если Set уже был вызван для флага с таким же именем. Это изменение предназначено для обнаружения случаев, когда изменения в порядке инициализации приводят к тому, что операции с флагами выполняются в другом порядке, чем ожидалось. Во многих случаях решение этой проблемы состоит в том, чтобы ввести явную зависимость пакета, чтобы правильно упорядочить определение перед любыми операциями Set.

go/ast

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

Новое поле File.GoVersion записывает минимальную версию Go, необходимую для любых директив //go:build или // +build.

go/build

Пакет теперь анализирует директивы сборки (комментарии, начинающиеся с //go:) в заголовках файлов (перед объявлением пакета). Эти директивы доступны в новых полях пакета: Directives, TestDirectives и XTestDirectives.

go/build/constraint

Новая функция GoVersion возвращает минимальную версию Go, подразумеваемую выражением сборки.

go/token

Новый метод File.Lines возвращает таблицу номеров строк файла в той же форме, которая принята File.SetLines.

go/types

Новый метод Package.GoVersion возвращает версию языка Go, использованную для проверки пакета.

hash/maphash

Пакет hash/maphash теперь имеет реализацию на чистом Go, которую можно выбрать с помощью тега сборки purego.

html/template

Новая ошибка ErrJSTemplate возвращается, когда действие появляется в литерале шаблона JavaScript. Ранее возвращалась неэкспортированная ошибка.

io/fs

Новая функция FormatFileInfo возвращает отформатированную версию FileInfo. Новая функция FormatDirEntry возвращает отформатированную версию DirEntry. Реализация DirEntry, возвращаемая ReadDir, теперь реализует метод String, который вызывает FormatDirEntry, и то же самое справедливо для значения DirEntry, переданного в WalkDirFunc.

math/big

Новый метод Int.Float64 возвращает ближайшее целое число с плавающей запятой вместе с указанием любого произошедшего округления.

net

В Linux пакет net теперь может использовать Multipath TCP, если ядро его поддерживает. По умолчанию он не используется. Чтобы использовать Multipath TCP, если он доступен на клиенте, вызовите метод Dialer.SetMultipathTCP перед вызовом методов Dialer.Dial или Dialer.DialContext. Чтобы использовать Multipath TCP, если он доступен на сервере, вызовите метод ListenConfig.SetMultipathTCP перед вызовом метода ListenConfig.Listen. Укажите сеть как "tcp", "tcp4" или "tcp6", как обычно. Если Multipath TCP не поддерживается ядром или удаленным хостом, соединение автоматически переключается на TCP. Чтобы проверить, использует ли конкретное соединение Multipath TCP, используйте метод TCPConn.MultipathTCP.

В будущем релизе Go возможно будет включен Multipath TCP по умолчанию в системах, которые его поддерживают.

net/http

Новый метод ResponseController.EnableFullDuplex позволяет обработчикам сервера одновременно читать тело запроса HTTP/1 во время записи ответа. Обычно сервер HTTP/1 автоматически потребляет оставшееся тело запроса перед началом записи ответа, чтобы избежать взаимоблокировки клиентов, которые пытаются записать полный запрос до чтения ответа. Метод EnableFullDuplex отключает такое поведение.

Новая ошибка ErrSchemeMismatch возвращается клиентом и транспортом, когда сервер отвечает на запрос HTTPS ответом HTTP.

Пакет net/http теперь поддерживает error.ErrUnsupported, поскольку выражение error.Is(http.ErrNotSupported, error.ErrUnsupported) вернет true.

os

Программы теперь могут передавать пустое значение time.Time функции Chtimes, чтобы оставить неизменным либо время доступа, либо время модификации.

В Windows метод File.Chdir теперь меняет текущий каталог на файл, а не всегда возвращает ошибку.

В системах Unix, если в NewFile передается неблокирующий дескриптор, вызов метода File.Fd теперь будет возвращать неблокирующий дескриптор. Ранее дескриптор был переведен в режим блокировки.

В Windows вызов Truncate для несуществующего файла используется для создания пустого файла. Теперь он возвращает ошибку, указывающую, что файл не существует.

В Windows при вызове TempDir теперь используется GetTempPath2W, если он доступен, вместо GetTempPathW. Новое поведение представляет собой меру усиления безопасности, которая предотвращает доступ к временным файлам, созданным процессами, работающими как SYSTEM, со стороны не-SYSTEM процессов.

В Windows пакет os теперь поддерживает работу с файлами, имена которых, сохраненные в формате UTF-16, не могут быть представлены как действительные UTF-8.

В Windows Lstat теперь разрешает символические ссылки для путей, заканчивающихся разделителем путей, в соответствии с его поведением на платформах POSIX.

Реализация интерфейса io/fs.DirEntry, возвращаемого функцией ReadDir и методом File.ReadDir, теперь реализует метод String, который вызывает io/fs.FormatDirEntry.

Реализация интерфейса io/fs.FS, возвращаемого функцией DirFS, теперь реализует интерфейсы io/fs.ReadFileFS и io/fs.ReadDirFS.

path/filepath

Реализация интерфейса io/fs.DirEntry, передаваемого в аргумент функции WalkDir, теперь реализует метод String, который вызывает io/fs.FormatDirEntry.

reflect

В Go 1.21 ValueOf больше не принудительно размещает свой аргумент в куче, позволяя размещать содержимое Value в стеке. Большинство операций с Value также позволяют размещать базовое значение в стеке.

Новый метод Value Value.Clear очищает содержимое карты или обнуляет содержимое среза. Это соответствует новой встроенной функции clear, добавленной в язык.

Типы SliceHeader и StringHeader устарели. В новом коде отдавайте предпочтение unsafe.Slice, unsafe.SliceData, unsafe.String или unsafe.StringData.

regexp

Regexp теперь определяет методы MarshalText и UnmarshalText. Они реализуют encoding.TextMarshaler и encoding.TextUnmarshaler и будут использоваться такими пакетами, как encoding/json.

runtime

Текстовые трассировки стека, создаваемые программами Go, например, при сбое, вызове runtime.Stack или сборе профиля горутины с debug=2, теперь включают в трассировку стека идентификаторы горутин, создавших каждую горутину.

Сбойные приложения Go теперь могут подключиться к отчетам об ошибках Windows (WER, Windows Error Reporting), установив переменную среды GOTRACEBACK=wer или вызвав debug.SetTraceback("wer") перед сбоем. За исключением включения WER, среда выполнения будет вести себя так же, как и при GOTRACEBACK=crash. В системах, отличных от Windows, GOTRACEBACK=wer игнорируется.

GODEBUG=cgocheck=2, тщательная проверка правил передачи указателей cgo, больше не доступен в качестве опции отладки. Вместо этого он доступен в качестве эксперимента с использованием GOEXPERIMENT=cgocheck2. В частности, это означает, что этот режим необходимо выбирать во время сборки, а не во время запуска.

GODEBUG=cgocheck=1 по-прежнему доступен (и по-прежнему используется по умолчанию).

В пакет среды выполнения добавлен новый тип Pinner. Пиннеры могут использоваться для "закрепления" памяти Go, чтобы ее можно было более свободно использовать кодом, отличным от Go. Например, теперь разрешена передача значений Go, которые ссылаются на закрепленную память Go, в код C. Ранее передача любой такой вложенной ссылки была запрещена правилами передачи указателей cgo.

runtime/metrics

Теперь доступны некоторые ранее внутренние показатели сборщика мусора, такие как размер динамической кучи. GOGC и GOMEMLIMIT теперь также доступны в качестве метрик.

runtime/trace

Сбор трассировок на amd64 и arm64 теперь требует существенно меньших затрат ЦП: до 10 раз больше, чем в предыдущей версии.

Трассировки теперь содержат явные события stop-the-world по любой причине, по которой среда выполнения Go может запустить stop-the-world, а не только для сборки мусора.

sync

Новые функции OnceFunc, OnceValue и OnceValues отражают распространенное использование Once для ленивой инициализации значения при первом использовании.

syscall

В Windows функция Fchdir теперь меняет текущий каталог на свой аргумент, а не всегда возвращает ошибку.

Во FreeBSD SysProcAttr имеет новое поле Jail, которое можно использовать для помещения вновь созданного процесса в изолированную среду.

В Windows пакет syscall теперь поддерживает работу с файлами, имена которых, сохраненные в формате UTF-16, не могут быть представлены как допустимые UTF-8. Функции UTF16ToString и UTF16FromString теперь преобразуют данные UTF-16 в строки WTF-8. Это обратно совместимо, поскольку WTF-8 является расширенным набором формата UTF-8, который использовался в более ранних релизах.

Несколько значений ошибок соответствуют новым error.ErrUnsupported, например, error.Is(err, error.ErrUnsupported) возвращает true.

  • ENOSYS
  • ENOTSUP
  • EOPNOTSUPP
  • EPLAN9 (только Plan 9)
  • ERROR_CALL_NOT_IMPLEMENTED (только Windows)
  • ERROR_NOT_SUPPORTED (только Windows)
  • EWINDOWS (только Windows)

testing

Новая опция -test.fullpath будет печатать полные пути в сообщениях журнала тестирования, а не только базовые имена.

Новая функция тестирования сообщает, является ли программа тестом, созданным go test.

testing/fstest

Вызов Open.Stat вернет тип, который теперь реализует метод String, вызывающий io/fs.FormatFileInfo.

unicode

Пакет unicode и связанная с ним поддержка во всей системе были обновлены до Unicode 15.0.0.

Порты

Darwin

Как объявлено в примечаниях к релизу Go 1.20, для Go 1.21 требуется macOS 10.15 Catalina или более поздняя версия; поддержка предыдущих версий прекращена.

Windows

Как объявлено в примечаниях к релизу Go 1.20, для Go 1.21 требуется как минимум Windows 10 или Windows Server 2016; поддержка предыдущих версий прекращена.

WebAssembly

Новую директиву go:wasmimport теперь можно использовать в программах Go для импорта функций с хоста WebAssembly.

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

Системный интерфейс WebAssembly

В Go 1.21 добавлен экспериментальный порт в системный интерфейс WebAssembly (WASI), предварительная версия 1 (GOOS=wasip1, GOARCH=wasm).

В результате добавления нового значения GOOS "wasip1" файлы Go с именем *_wasip1.go теперь будут игнорироваться инструментами Go, за исключением случаев, когда используется это значение GOOS. Если у вас есть имена файлов, соответствующие этому шаблону, вам нужно будет переименовать их.

ppc64/ppc64le

В Linux GOPPC64=power10 теперь генерирует инструкции для PC, инструкции с префиксами и другие новые инструкции Power10. В AIX GOPPC64=power10 генерирует инструкции Power10, но не создает инструкции, относящиеся к PC.

При построении позиционно-независимых двоичных файлов для GOPPC64=power10 GOOS=linux GOARCH=ppc64le пользователи могут ожидать уменьшения размера двоичных файлов в большинстве случаев, в некоторых случаях на 3,5%. Независимые от позиции двоичные файлы создаются для ppc64le со следующими значениями -buildmode: c-archive, c-shared, shared, pie, plugin.

loong64

Порт linux/loong64 теперь поддерживает -buildmode=c-archive, -buildmode=c-shared и -buildmode=pie.


Читайте также: