Примечания к выпуску Go 1.15

Введение в Go 1.15

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

Go 1.15 включает существенные улучшения в компоновщике, улучшает выделение памяти для маленьких объектов при высоком количестве ядер и устаревает X.509 CommonName. GOPROXY теперь поддерживает пропуск прокси, возвращающих ошибки, и добавлен новый встроенный пакет tzdata.

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

Изменений в языке нет.

Платформы

Darwin

Как было объявлено в примечаниях к выпуску Go 1.14, Go 1.15 требует macOS 10.12 Sierra или новее; поддержка предыдущих версий прекращена.

Как было объявлено в примечаниях к выпуску Go 1.14, Go 1.15 прекращает поддержку 32-битных бинарных файлов на macOS, iOS, iPadOS, watchOS и tvOS (порт darwin/386 и darwin/arm). Go продолжает поддерживать 64-битные порты darwin/amd64 и darwin/arm64.

Windows

Go теперь генерирует исполняемые файлы Windows ASLR, когда используется флаг -buildmode=pie в cmd/link. Команда Go использует -buildmode=pie по умолчанию в Windows.

Флаги -race и -msan теперь всегда включают -d=checkptr, который проверяет использование unsafe.Pointer. Ранее это было так на всех ОСах, кроме Windows.

Go-созданные DLL больше не приводят к завершению процесса при получении сигнала (например, Ctrl-C в терминале).

Android

При компоновке бинарных файлов для Android Go 1.15 явно выбирает компоновщик lld, доступный в последних версиях NDK. Компоновщик lld избегает сбоев на некоторых устройствах и планируется сделать его компоновщиком по умолчанию в будущих версиях NDK.

OpenBSD

Go 1.15 добавляет поддержку OpenBSD 6.7 на GOARCH=arm и GOARCH=arm64. Предыдущие версии Go уже поддерживали OpenBSD 6.7 на GOARCH=386 и GOARCH=amd64.

RISC-V

Был достигнут прогресс в улучшении стабильности и производительности 64-битного порта RISC-V в Linux (GOOS=linux, GOARCH=riscv64). Теперь он также поддерживает асинхронную предотвращающую предemption.

386

Go 1.15 — последний выпуск, поддерживающий аппаратное обеспечение с плавающей точкой только x87 (GO386=387). В будущих выпусках потребуется хотя бы поддержка SSE2 на 386, что повысит минимальные требования GOARCH=386 до Intel Pentium 4 (выпущенного в 2000 году) или AMD Opteron/Athlon 64 (выпущенного в 2003 году).

Инструменты

Команда go

Переменная окружения GOPROXY теперь поддерживает пропуск прокси, возвращающих ошибки. URL-адреса прокси теперь могут быть разделены либо запятыми (,), либо вертикальной чертой (|). Если URL прокси сопровождается запятой, команда go попытается перейти к следующему прокси в списке после ответа HTTP 404 или 410. Если URL прокси сопровождается вертикальной чертой, команда go попытается перейти к следующему прокси в списке после любой ошибки. Обратите внимание, что значение по умолчанию GOPROXY остается https://proxy.golang.org,direct, которое не переходит к direct в случае ошибок.

go test

Изменение флага -timeout теперь приводит к недействительности кэшированных результатов тестов. Кэшированный результат для запуска теста с длинным таймаутом больше не будет считаться успешным при повторном вызове go test с коротким таймаутом.

Разбор флагов

Исправлены различные проблемы разбора флагов в go test и go vet. В частности, флаги, указанные в GOFLAGS, теперь обрабатываются более последовательно, а флаг -outputdir теперь интерпретирует относительные пути относительно рабочей директории команды go (а не рабочей директории каждого отдельного теста).

Кэш модулей

Расположение кэша модулей теперь может быть задано с помощью переменной окружения GOMODCACHE. Значение по умолчанию для GOMODCACHEGOPATH[0]/pkg/mod, то есть расположение кэша модулей до этого изменения.

Теперь доступно обходное решение для ошибок «Access is denied» в Windows при выполнении команд go, которые обращаются к кэшу модулей, вызванных внешними программами, одновременно сканирующими файловую систему (см. issue #36568). Обходное решение по умолчанию не включено, поскольку оно не безопасно при одновременном запуске версий Go ниже 1.14.2 и 1.13.10 с одним и тем же кэшем модулей. Его можно включить, явно установив переменную окружения GODEBUG=modcacheunzipinplace=1.

Vet

Новое предупреждение для string(x)

Инструмент vet теперь предупреждает о преобразованиях вида string(x), где x имеет целочисленный тип, отличный от rune или byte. Опыт использования Go показал, что многие преобразования этого вида ошибочно предполагают, что string(x) даёт строковое представление целого числа x. На самом деле, это выражение вычисляется как строка, содержащая UTF-8 кодирование значения x. Например, string(9786) не даёт строку "9786"; он вычисляется как строка "\xe2\x98\xba", или "☺".

Код, который правильно использует string(x), может быть переписан как string(rune(x)). В некоторых случаях, вызов utf8.EncodeRune(buf, x) с подходящим байтовым срезом buf может быть правильным решением. Другой код, вероятно, должен использовать strconv.Itoa или fmt.Sprint.

Эта новая проверка vet включена по умолчанию при использовании go test.

Мы рассматриваем возможность запретить такое преобразование в будущем выпуске Go. То есть, язык будет изменён таким образом, чтобы разрешало использование string(x) только для целочисленного x, если тип xrune или byte. Такое изменение языка не будет обратно совместимым. Мы используем эту проверку vet как первый шаг к изменению языка.

Новое предупреждение для невозможных преобразований интерфейсов

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

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

Эта новая проверка vet включена по умолчанию при использовании go test.

Мы рассматриваем возможность запретить невозможные утверждения типа интерфейсов в будущем выпуске Go. Такое изменение языка не будет обратно совместимым. Мы используем эту проверку vet как первый шаг к изменению языка.

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

Если функция panic вызывается со значением, тип которого является производным от любого из следующих типов: bool, complex64, complex128, float32, float64, int, int8, int16, int32, int64, string, uint, uint8, uint16, uint32, uint64, uintptr, то значение будет напечатано, а не только его адрес. Ранее это было верно только для значений точного типа.

В системе Unix, если команда kill или системный вызов kill используется для отправки сигнала SIGSEGV, SIGBUS, или SIGFPE в программу на Go, и если сигнал не обрабатывается через os/signal.Notify, то программа на Go теперь надежно завершится с трассировкой стека. В предыдущих версиях поведение было непредсказуемым.

Распределение памяти для небольших объектов теперь работает гораздо эффективнее при высоком количестве ядер и имеет меньшую максимальную задержку.

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

Неблокирующие получения из закрытых каналов теперь работают так же эффективно, как и неблокирующие получения из открытых каналов.

Компилятор

Правила безопасности пакета unsafe разрешают преобразование unsafe.Pointer в uintptr при вызове определенных функций. Ранее, в некоторых случаях, компилятор позволял несколько последовательных преобразований (например, syscall.Syscall(…, uintptr(uintptr(ptr)), …)). Теперь компилятор требует ровно одно преобразование. Код, использующий несколько преобразований, должен быть обновлён для соответствия правилам безопасности.

Go 1.15 уменьшает типовой размер бинарных файлов примерно на 5% по сравнению с Go 1.14, убирая определённые типы метаданных GC и более агрессивно удаляя неиспользуемые метаданные типов.

Инструментарий теперь устраняет ошибку процессора Intel SKX102 на GOARCH=amd64, выравнивая функции по границам в 32 байта и добавляя заполнение инструкций переходов. Хотя это увеличивает размеры бинарных файлов, это компенсируется улучшениями размеров, упомянутыми выше.

Go 1.15 добавляет флаг -spectre как в компилятор, так и в ассемблер, чтобы разрешить включение защиты от уязвимостей Spectre. Эти настройки почти никогда не требуются и предоставляются в основном как механизм "защита в глубину". См. страницу вики Spectre для получения подробностей.

Компилятор теперь отклоняет директивы компилятора //go:, которые не имеют смысла для объявления, к которому они применяются, с ошибкой "неправильное расположение директивы компилятора". Такие неправильно применённые директивы были сломаны ранее, но компилятор игнорировал их без уведомления.

Журнал оптимизации компилятора -json теперь отображает большие (>= 128 байт) копии и включает объяснения решений анализа утечек.

Линкер

В этом выпуске включены существенные улучшения линкера Go, которые снижают использование ресурсов линкера (время и память) и повышают надёжность и поддерживаемость кода.

Для репрезентативного набора больших программ на Go, компоновка происходит на 20% быстрее и требует на 30% меньше памяти в среднем для ОС на основе ELF (Линукс, FreeBSD, NetBSD, OpenBSD, Dragonfly и Solaris) работающих на архитектуре amd64, с более скромными улучшениями для других комбинаций архитектур/ОС.

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

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

Компоновщик теперь по умолчанию использует внутренний режим компоновки для -buildmode=pie на linux/amd64 и linux/arm64, поэтому эти конфигурации больше не требуют C-компоновщика. Внешний режим компоновки (который был режимом по умолчанию в Go 1.14 для -buildmode=pie) может быть включён с помощью флага -ldflags=-linkmode=external.

Objdump

Утилита objdump теперь поддерживает дизассемблирование в синтаксисе GNU assembler с помощью флага -gnu.

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

Новый встроенный пакет tzdata

Go 1.15 включает новый пакет time/tzdata, который позволяет встраивать базу данных часовых поясов в программу. Импортирование этого пакета (в виде import _ "time/tzdata") позволяет программе находить информацию о часовом поясе даже если база данных часовых поясов недоступна в локальной системе. Также можно встроить базу данных часовых поясов при сборке с флагом -tags timetzdata. Оба подхода увеличивают размер программы примерно на 800 КБ.

Cgo

В Go 1.15 тип C EGLConfig будет преобразован в тип Go uintptr. Это изменение аналогично тому, как Go 1.12 и более поздние версии обрабатывают типы EGLDisplay, CoreFoundation в Darwin и JNI типы в Java. Дополнительную информацию можно найти в документации cgo.

Начиная с Go 1.15.3, cgo не будет разрешать Go-коду выделять неопределённый тип структуры (C-структура, определённая просто как struct S; или аналогично) на стеке или куче. Go-код будет разрешён использовать только указатели на такие типы. Выделение экземпляра такой структуры и передача указателя или полного значения структуры в C-код всегда было небезопасным и маловероятно работало корректно; теперь это запрещено. Исправление заключается либо в переписывании Go-кода с использованием только указателей, либо в обеспечении того, чтобы Go-код видел полное определение структуры, включив соответствующий заголовочный файл C.

Устаревшая обработка CommonName в X.509

Устаревшее, legacy поведение, при котором поле CommonName в сертификатах X.509 рассматривалось как имя хоста, когда альтернативные имена субъекта отсутствуют, теперь отключено по умолчанию. Временно его можно снова включить, добавив значение x509ignoreCN=0 в переменную окружения GODEBUG.

Обратите внимание, что если CommonName является недопустимым именем хоста, оно всегда игнорируется, независимо от настроек GODEBUG. Недопустимые имена включают те, которые содержат символы отличные от букв, цифр, дефисов и подчёркиваний, а также те, у которых пустые метки или завершающие точки.

Мелкие изменения в библиотеке

Как и всегда, в библиотеке были внесены различные мелкие изменения и обновления, сделанные с учётом обещания совместимости Go 1.

bufio

Когда Scanner используется с некорректным io.Reader, который неправильно возвращает отрицательное число из метода Read, Scanner больше не будет паниковать, а вместо этого будет возвращать новую ошибку ErrBadReadCount.

context

Создание производного Context с использованием nil родителя теперь явно запрещено. Любая попытка сделать это с помощью функций WithValue, WithDeadline или WithCancel вызовет панику.

crypto

Типы PrivateKey и PublicKey в пакетах crypto/rsa, crypto/ecdsa и crypto/ed25519 теперь имеют метод Equal для сравнения ключей на эквивалентность или для создания типобезопасных интерфейсов для открытых ключей. Сигнатура метода совместима с определением равенства из go-cmp.

Hash теперь реализует fmt.Stringer.

crypto/ecdsa

Новые функции SignASN1 и VerifyASN1 позволяют генерировать и проверять ECDSA-подписи в стандартном кодировании ASN.1 DER.

crypto/elliptic

Новые функции MarshalCompressed и UnmarshalCompressed позволяют кодировать и декодировать точки эллиптических кривых NIST в сжатом формате.

crypto/rsa

VerifyPKCS1v15 теперь отклоняет недопустимые короткие подписи с отсутствующими ведущими нулями, согласно RFC 8017.

crypto/tls

Новый тип Dialer и его метод DialContext позволяют использовать контекст как для установления соединения, так и для выполнения handshake с TLS-сервером.

Новый обратный вызов VerifyConnection в типе Config позволяет реализовать пользовательскую логику проверки для каждого соединения. Он имеет доступ к ConnectionState, который включает сертификаты узла, SCT и stapled OCSP-ответы.

Ключи сессионных тикетов, автоматически генерируемые в TLS, теперь автоматически вращаются каждые 24 часа, с продолжительностью жизни 7 дней, чтобы ограничить их влияние на защиту forward secrecy.

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

Проверки защиты от понижения версии клиента, указанные в RFC 8446, теперь принудительно применяются. Это может привести к ошибкам соединения для клиентов, встречающихся с middleboxes, ведущими себя как несанкционированные атаки на понижение версии.

SignatureScheme, CurveID и ClientAuthType теперь реализуют fmt.Stringer.

Поля OCSPResponse и SignedCertificateTimestamps в типе ConnectionState теперь заполняются повторно при возобновлении клиентских соединений.

tls.Conn теперь возвращает прозрачную ошибку для постоянно разорванных соединений, обёртывая временную net.Error. Чтобы получить доступ к оригинальной net.Error, следует использовать errors.As (или errors.Unwrap), а не утверждение типа.

crypto/x509

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

Новая функция CreateRevocationList и тип RevocationList позволяют создавать списки отозванных сертификатов X.509 v2, соответствующие стандарту RFC 5280.

Функция CreateCertificate теперь автоматически генерирует SubjectKeyId, если шаблон является центром сертификации (CA) и не задаёт его явно.

Функция CreateCertificate теперь возвращает ошибку, если шаблон указывает MaxPathLen, но не является центром сертификации (CA).

В системах Unix, отличных от macOS, переменная окружения SSL_CERT_DIR теперь может быть списком, разделённым двоеточием.

В macOS бинарные файлы теперь всегда связываются с Security.framework для извлечения корневых доверенных сертификатов, независимо от того, доступен ли cgo. Результатом станет более согласованное поведение с верификатором ОС.

crypto/x509/pkix

Метод Name.String теперь выводит нестандартные атрибуты из Names, если ExtraNames равно nil.

database/sql

Новый метод DB.SetConnMaxIdleTime позволяет удалять соединение из пула соединений после того, как оно простаивает в течение определённого времени, независимо от общего времени жизни соединения. Поле DBStats.MaxIdleTimeClosed показывает общее количество соединений, закрытых из-за DB.SetConnMaxIdleTime.

Новый геттер Row.Err позволяет проверять ошибки запроса без вызова Row.Scan.

database/sql/driver

Новый интерфейс Validator может быть реализован типом Conn, чтобы драйверы могли сигнализировать, действительно ли соединение допустимо или его следует отбросить.

debug/pe

Пакет теперь определяет константы IMAGE_FILE, IMAGE_SUBSYSTEM, и IMAGE_DLLCHARACTERISTICS, используемые в формате файлов PE.

encoding/asn1

Marshal теперь сортирует компоненты SET OF согласно X.690 DER.

Unmarshal теперь отклоняет теги и идентификаторы объектов, которые не закодированы минимально согласно X.690 DER.

encoding/json

В пакете теперь есть внутреннее ограничение на максимальную глубину вложенности при декодировании. Это снижает вероятность того, что глубоко вложенный входной поток может использовать большие объемы стековой памяти, или даже вызвать панику “goroutine stack exceeds limit”.

flag

Когда пакет flag встречает флаги -h или -help, и эти флаги не определены, он теперь выводит сообщение об использовании. Если FlagSet был создан с помощью ExitOnError, FlagSet.Parse затем выходит со статусом 2. В этом релизе статус выхода для -h или -help был изменен на 0. Это особенно относится к стандартной обработке флагов командной строки.

fmt

Инструкции печати %#g и %#G теперь сохраняют конечные нули для значений с плавающей точкой.

go/format

Функции Source и Node теперь нормализуют префиксы и экспоненты числовых литералов как часть форматирования исходного кода Go. Это соответствует поведению команды gofmt, реализованной начиная с Go 1.13.

html/template

Пакет теперь использует Unicode-эскейпы (\uNNNN) во всех контекстах JavaScript и JSON. Это исправляет ошибки экранирования в контекстах application/ld+json и application/json.

io/ioutil

TempDir и TempFile теперь отклоняют шаблоны, содержащие разделители путей. То есть вызовы вроде ioutil.TempFile("/tmp", "../base*") больше не будут успешными. Это предотвращает непреднамеренное перемещение по директориям.

math/big

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

math/cmplx

Функции в этом пакете были обновлены для соответствия стандарту C99 (Приложение G, совместимая с IEC 60559 арифметика комплексных чисел) в части обработки специальных аргументов, таких как бесконечность, NaN и знаковый ноль.

net

Если операция ввода-вывода превышает установленный срок действия с помощью методов Conn.SetDeadline, Conn.SetReadDeadline, или Conn.SetWriteDeadline, то теперь она возвращает ошибку, которая является или обёрткой os.ErrDeadlineExceeded. Это может использоваться для надежного определения, была ли ошибка вызвана превышением срока действия. Ранее рекомендовалось вызывать метод Timeout на ошибке, но операции ввода-вывода могут возвращать ошибки, для которых Timeout возвращает true, хотя срок действия не был превышен.

Новый метод Resolver.LookupIP поддерживает поиски IP-адресов, которые являются как специфичными для сети, так и принимают контекст.

net/http

Анализ теперь строже, как мера ужесточения против атак методом запроса-смугглинга: непечатаемые пробельные символы, отличные от ASCII, больше не обрезаются, как SP и HTAB, и поддержка Transfer-Encoding со значением identity была удалена.

net/http/httputil

ReverseProxy теперь поддерживает возможность не изменять заголовок X-Forwarded-For, если запись входящего Request.Header для этого поля равна nil.

Когда запрос Switching Protocol (например, WebSocket), обрабатываемый ReverseProxy, отменяется, бэкендное соединение теперь корректно закрывается.

net/http/pprof

Все конечные точки профилирования теперь поддерживают параметр “seconds”. Если этот параметр задан, то конечная точка профилирует заданное количество секунд и выводит разницу. Значение параметра “seconds” в профайле cpu и в конечных точках трассировки остаётся прежним.

net/url

Новое поле URL RawFragment и метод EscapedFragment обеспечивают детальную информацию и контроль над точным кодированием фрагмента URL. Эти элементы аналогичны RawPath и EscapedPath.

Новый метод URL Redacted возвращает URL в строковом виде с заменой пароля на xxxxx.

os

Если операция ввода-вывода превышает установленный срок действия с помощью методов File.SetDeadline, File.SetReadDeadline, или File.SetWriteDeadline, он теперь возвращает ошибку, которая является или оборачивает os.ErrDeadlineExceeded. Это позволяет надежно определить, является ли ошибка следствием превышения срока действия. В более ранних версиях рекомендовалось вызывать метод Timeout для ошибки, но операции ввода-вывода могут возвращать ошибки, для которых метод Timeout возвращает true, даже если срок действия не был превышен.

Пакеты os и net теперь автоматически повторяют системные вызовы, завершившиеся неудачей с кодом EINTR. Ранее это приводило к ложным ошибкам, которые стали более частыми в Go 1.14 с добавлением асинхронной предемпции. Сейчас это обрабатывается прозрачно.

Тип os.File теперь поддерживает метод ReadFrom. Это позволяет использовать системный вызов copy_file_range на некоторых системах при использовании io.Copy для копирования данных из одного os.File в другой. В результате io.CopyBuffer не всегда будет использовать предоставленный буфер при копировании в os.File. Если программе требуется принудительно использовать предоставленный буфер, это можно сделать следующим образом: io.CopyBuffer(struct{ io.Writer }{dst}, src, buf).

plugin

Генерация DWARF теперь поддерживается (и включена по умолчанию) для -buildmode=plugin на macOS.

Сборка с помощью -buildmode=plugin теперь поддерживается на freebsd/amd64.

reflect

Пакет reflect теперь запрещает доступ к методам всех недженериковых полей, тогда как ранее разрешал доступ к методам недженериковых, встроенных полей. Код, который полагается на предыдущее поведение, должен быть обновлён для доступа к соответствующему продвигаемому методу содержащей переменной.

regexp

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

runtime

Несколько функций, включая ReadMemStats и GoroutineProfile, больше не блокируются, если выполняется сборка мусора.

runtime/pprof

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

strconv

Добавлены функции FormatComplex и ParseComplex для работы с комплексными числами.

FormatComplex преобразует комплексное число в строку вида (a+bi), где a и b — это действительная и мнимая части.

ParseComplex преобразует строку в комплексное число заданной точности. ParseComplex принимает комплексные числа в формате N+Ni.

sync

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

Метод Map.Delete стал более эффективным.

syscall

В системах Unix функции, использующие SysProcAttr, теперь отклоняют попытки установить одновременно поля Setctty и Foreground, так как они оба используют поле Ctty, но делают это несовместимым образом. Ожидается, что немногие существующие программы устанавливают оба поля.

Установка поля Setctty теперь требует, чтобы поле Ctty было установлено в номер дескриптора файла в дочернем процессе, как определено полем ProcAttr.Files. Использование дочернего дескриптора всегда работало, но существовали определенные случаи, когда использование родительского дескриптора также срабатывало. Некоторые программы, устанавливающие Setctty, должны изменить значение Ctty, чтобы использовать номер дочернего дескриптора.

Теперь возможно вызывать системные вызовы, возвращающие значения с плавающей точкой на windows/amd64.

testing

Тип testing.T теперь имеет метод Deadline, который сообщает время, когда тестовый бинарник превысит установленный таймаут.

Функция TestMain больше не обязана вызывать os.Exit. Если функция TestMain возвращает, тестовый бинарник вызовет os.Exit с значением, возвращённым m.Run.

Новые методы T.TempDir и B.TempDir возвращают временные директории, которые автоматически очищаются в конце теста.

go test -v теперь группирует вывод по имени теста, вместо того чтобы печатать имя теста в каждой строке.

text/template

JSEscape теперь последовательно использует Юникодные экранирования (\u00XX), которые совместимы с JSON.

time

Новый метод Ticker.Reset поддерживает изменение длительности тикера.

При возврате ошибки, ParseDuration теперь заключает исходное значение в кавычки.

GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang