Go Update
3.11K subscribers
8 photos
73 links
Канал про новости связанные с языком программирования Go. Эволюция языка, стандартной библиотеки и просто интересные вещи над которыми работает Go Core Team и не только.

Админ: @lepage_d
Download Telegram
Дайджест активных предложений и дискуссий Go Core Team:

- spec: add untyped builtin zero: почти принят, о нем можно почитать тут.
- proposal: time: stop requiring Timer/Ticker.Stop for prompt GC: облегчающее жизнь изменение. Теперь не нужно вызывать Stop у таймера, что-бы его собрал сборщик мусора до истечения этого самого таймера. А это значит код типо case <- time.After(time.Minute): больше не приводит к утечкам, которые заметны на нагруженных местах.
- proposal: testing: add identity function that forces evaluation for benchmarks: бенчмарки пытаются научить не оптимизировать код внутри самого цикла бенчмарка. Иначе результаты могут показывать совсем не то, что вы думаете.
- proposal: cmd/compile: add new range behind GOEXPERIMENT=range: range над кастомными функциями идет в main бранч и будет скрыт под флагом.
- maps: remove Keys and Values for Go 1.21: из будущего пакета maps удалили две функции которые позволяли получить слайс ключей и слайс значений. Аргументируют, что в 1.22 завезут итераторы и хотят красивые имена сохранить для них.
- maps: remove package for Go 1.21: а вот сам пакет мы убирать не будем, много в нем хорошего и кроме тех двух функций.

Полный список - тут.
👍10🔥83
Релиз Go 1.21

Вот и состоялся релиз новой версии Go. Кроме того, что указано здесь, у нас так-же появились:

- Довольной большой пакет slices: среди прочего содержит функции Min / Max, функцию сортировки и функцию поиска в сортированном слайсе. И больше не нужно писать страшные блоки вставки и удаления элементов из слайса.
- Пакет maps: по сравнению со слайсами как-то бедновато, но есть удобная функция копирования.
- Пакет cmp: содержит обьявление всех сравниваемых по порядку типов и две базовые функции для работы с ними. Нужно скорее для пакетов maps и slices, а так-же разработчикам библиотек с коллекциями.
- Profile-guide optimization (PGO - оптимизация основанная на данных профилировки) вышла из превью и теперь применяется всегда если присутствует файл default.pgo в директории main пакета. Говорят, что благодаря ей удалось ускорить компилятор примерно на 6%.
- Улучшение пакета context: теперь можно вешать функцию на отмену контекста (удобно когда вам нужно закрыть канал или прекратить чтение из сокета) и отвязать дочерний контекст от отмены родителя.
- При выводе очень глубоких стеков теперь показывают 50 самых верхних и 50 самых нижних фреймов (названий функции) вместо 100 самых верхних как это было ранее. Должно помочь с отладкой паник в рекурсивных функциях.
👍58🔥10
И снова про итераторы…

Если прошлое предложение от Расса показывало как будут выглядеть итераторы, то новое предложение показывает как мы будем ими пользоваться и готовит для этого огромный фундамент.

У нас появятся новый пакет iter и два новых типа: Seq[V any] и Seq2[K, V any] которые будут описывать итераторы. Общий тип просили в первом обсуждении итераторов.

У нас будет четкий стандарт именования функций которые возвращают итераторы.

Если итерация может провалится, правильным и идиоматичным типом итератора будет iter.Seq2[MyType, error]. Соответсвенно каждый шаг сможет сам проверить себя на ошибку.

Нам дадут функцию для преобразования наших pull итераторов в push: func iter.Pull(seq iter.Seq[K,V]) (func() (K, V), stop func()) которая возвращает функцию для получения следующего элемента из итератора и функцию для его остановки. Здесь Расс еще раз напоминает, что писать push итераторы проще, процесс подготовки к работе и очистки у них делается в рамках одного потока управления, а не в разных функциях. А чем проще, тем меньше шанс совершить ошибку.

‼️ И главное: нам сразу подвезут кучу обновлений пакетов: strings, bytes, regexp а так-же обновления недавних slices и maps. Самих новых функций там очень много, судя по всему Расс учел опыт добавления дженериков, когда новую фичу привезли, а вот изменений в стандартную библиотеку под нее не привезли. Так же нас ждет пакет xiter (правда пока в exp модуле) которые даст большое число операций над этими самыми итераторами. Да-да ваши любимые Map, Filter, Concat, Merge, Zip — все это там будет.

Сам proposal состоит из нескольких частей, там довольно много и подробно описано, поэтому если хотите вникнуть - рекомендую ознакомится с оригиналом. А сам релиз Go 1.22 похоже обещает быть не менее интересным чем релиз Go 1.18. Ждем…
🔥171
Короче теперь мы Java. Можно ынтыпрайз пилить.
😁32🗿112
Персональная запись: сегодня мне исполнился 31 год.

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

Идея вести такой список заметок по Go родилась спонтанно. Я довольно часто скидывал в чатики инфу про новые фичи или интересные, на мой взгляд, обсуждения в сообществе. Предложения от разработчиков языка, предложения от сообщества, тренд общей эволюции языка и свои, не редко критичные, мысли по этому поводу. Обьяснения зачем эти нововведения вообще нужны. После одного из таких сообщений, Коля Тузов (@justskiv) предложил мне начать вести блог, куда я буду структурированно это все писать. Структурированно требует сил и времени, это не напишешь в двух словах ибо нужно попытаться развить и обьяснить свою мысль. По этой причине я изначально отказывался.

Но потом, после очередного настойчивого предложения от Коли 😄, мне стало понятно, что число и смысл обсуждений, за которыми я слежу, начинает выпадать из моей памяти. А главное выпадают мысли по поводу этих обсуждений и нововведений. И стало понятно, что ценность такого блога будет не только в том, что увидят другие, но и в том, что спустя время смогу увидеть я и вспомнить свои собственные мысли. Такие заметки на полях имеют ценность сами по себе. И я наконец решился…

Из других изменений: я недавно побывал в Чили. Про этот опыт мы скорее всего будем делать подкаст с Колей, вместе с обуждением работы над опенсорс проектом в распределенной команде — там есть о чем рассказать и подумать, как для тех кто думает о релокации, так и для тех кто считает что Латинская Америка это «апельсины, анаконда и амазонка».

Вообще отслеживание изменений это очень интересная штука. Когда я создавал этот канал, я думал тут будет максимум 100 подписчиков, так как тема довольно специфична. Как мне казалось большинству разработчиков вообще все равно, что там под капотом и куда движется сам язык (моя личная боль на собеседованиях). Однако нас уже больше 800 и восходящий тренд, судя по всему, не собирается останавливаться. За что отдельное спасибо всем и каждому из вас: если кто-то из вас узнал что-то новое для себя из моих записок, значит это все было не зря.

О будущем: в ноябре, если все пойдет нормально, я буду выступать на GolangConf 2023 с докладом про эволюцию языка, где я попытаюсь структурировать все те изменение которые мы видели за последние годы и так-же те изменения которые нам только предстоит увидеть. Попытаюсь поводить руками над прозрачным шаром вывести тренд. Язык действительно теряет частичку своей простоты, но я уверен, что мы по прежнему сможем найти тот баланс между простотой и удобством, которые находили все эти годы. Мы уже проходили все это с каналами и контекстами, сможем и тут.

А в заключении вот что: такая запись это исключение. Моей изначальной идеей был и остается строго технический канал который охватывает ядро языка и небольшую часть экосистемы вокруг. Уже существует достаточно каналов которые рассказывают про новые библиотеки или крутые истории от пользователей языка. А вести блог про свои мысли о реальности в целом я бы наверное не стал: уже и так есть большое число людей, которые транслируют поток своего мозга в интернет 24/7.

Но все же, как мне кажется, один раз в году можно сделать такое допущение. В конце концов, будет о чем подумать ровно через год, в этот день и месяц.

И конечно же: Show must go on…
🔥76👏12👍109
📝 Изменение формата имени версий Go начиная с Go 1.21

Начиная с Go 1.21 любая версия Go теперь всегда именуется как Go x.yy.zz взамен старого формата x.yy[.zz] где .zz не применялось для первого релиза внутри версии.

Проще всего понять на примерах:
→ Ранее Go 1.20 был и именем версии языка и именем первого релиза в ней. Т.е. для первого релиза go version возвращал go version go1.20 linux/amd64 для второго релиза go version go1.20.1 linux/amd64 и так далее.
→ Начиная с Go 1.21 это только имя версии языка. Первый релиз в этой версии называется 1.21.0. Т.е. для первого релиза go version возвращает go version go1.21.0 linux/amd64 для второго релиза go version go1.21.1 linux/amd64 и так далее.

Т.е. первый релиз в версии теперь всегда содержит в конце ноль.

А важно это по одной простой причине:
- Для первого релиза Go 1.20 была ссылка на скачивание https://storage.googleapis.com/golang/go1.20.linux-amd64.tar.gz
- Для первого релиза Go 1.21 ссылка на скачивание стала https://storage.googleapis.com/golang/go1.21.0.linux-amd64.tar.gz а старый формат ссылки выдаст 404.

Не пропустите это когда будете обновлять ваши CI скрипты.
👍201
… Оказывается Телеграм считает ветку комментариев к каждому сообщению в канале отдельно, а просто сообщения в общий чат идут отдельно, но сам общий чат содержит в себе все комментарии. Из-за этого часть моих ответов, которые были без цитирования, походу никто не увидел вообще, хах.

Ссылка на общий чат.
🗿5👍3
🟢 Быстрая установка нужной версии компилятора Go без замены текущей.

Раз пошло обсуждение о том, как установить Go 1.21 не удаляя старую (и без менеджеров пакетов) — на самом деле все довольно просто:

$ go install golang.org/dl/go1.21.0@latest
$ go1.21.0 download

$ go1.21.0 run main.go

Для текущего мастера:

$ go install golang.org/dl/gotip@latest
$ gotip download

$ gotip run main.go

Полный список https://pkg.go.dev/golang.org/dl - там есть версии Go до 1.5 включительно.

gotip кстати умный - ему можно скормить бранч через gotip download BRANCHNAME или конкретный CL (PR) через gotip download CL-NUMBER. Номер всегда видно в конкретном ревью - например для https://go-review.googlesource.com/c/tools/+/518376/ комманда будет gotip download 518376.

Вот так легко можно поиграться с фичами Go которые еще находятся в разработке.
🔥26👍8
Go Update pinned «🟢 Быстрая установка нужной версии компилятора Go без замены текущей. Раз пошло обсуждение о том, как установить Go 1.21 не удаляя старую (и без менеджеров пакетов) — на самом деле все довольно просто: $ go install golang.org/dl/go1.21.0@latest $ go1.21.0…»
Улучшенный эскейп анализ для слайсов байт полученных из строк.

Из маленького, но приятного: наконец решили и закрыли одну из четырехзначных задач (сие значит очень старая задача, скорее всего еще из старого трекера) - #2205 read-only escape analysis and avoiding string -> []byte copies.

Допустим у вас есть код:

package main

import (
"strings"
"testing"
)

var Index int

func BenchmarkStrToSlice(b *testing.B) {
someStr := strings.Repeat("HELLO WORLD", 6)

for i := 0; i < b.N; i++ {
Index = indexByte([]byte(someStr), 'D')
}
}

func indexByte(s []byte, c byte) int {
// Я про bytes.IndexByte(s, c) которая быстрее.
// Эта функция здесь находится для демонстрации.
for i, b := range s {
if b == c {
return i
}
}

return -1
}

Сейчас вызов go test -benchmem -bench . выдаст примерно такие результаты:

BenchmarkStrToSlice-10 46341886 22.75 ns/op 80 B/op 1 allocs/op

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

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

На gotip test -benchmem -bench . результаты обнадеживают:

BenchmarkStrToSlice-10 248279863. 4.707 ns/op 0 B/op 0 allocs/op

Никаких больше копий при конвертации из строки в слайс, если мы будем только читать из слайса.
👍42🔥112
cmp: add Or

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

Я уже говорил о том, что proposal о zero ждут авторы кода с дженериками? Так вот это тот самый случай: сейчас cmp.Or нельзя реализовать без использования констрейнта comparable на дженериках. Который, в свою очередь, не работает с любыми типами внутри которых есть несравниваемые поля - например слайсы. А разгадка проста: для сравнения с нулем/пустой переменной сейчас авторы дженерик кода вынуждены создавать пустую переменную и проводить сравнивание с ней. Что довольно сильно ограничивает список типов с которыми такой код может работать.

Ссылка для желающих поиграться на практике.
👍5😐3👀2
🐞reflect: Value.IsZero should report true for negative zero

Довольно интересный баг в реализации reflect.Value.IsZero который происходит из попытки ответить на вопрос: а что выведет вот такой код?

val := math.Copysign(0, -1) // Создаем float64(-0.0)
println(val == 0, reflect.ValueOf(val).IsZero())

В Go 1.20 и 1.21 ответ будет true false

Реализация обработки чисел с плавающей точкой внутри IsZero в версиях 1.21 и ниже вызывает функцию math.Float64bits и затем сравнивает результат с 0. Это верно для общего случая, но вот для числа -0 результат вызова этой функции будет совсем не 0. При этом Go компилятор корректно обрабатывает такое сравнение в обычном коде, что и приводит к разным результатам.

Баг уже исправлен и фикс будет включен в Go 1.22. Так как этот фикс приводит к изменению поведения его скорее всего не будет в багфиксах существующих релизов.

П.С: Про интересное скоро будет, мне пока чудовищно не хватает времени.
😨17🔥2👍1
Про интересное: intern package proposal

Практически все разработчики сталкиваются с проблемой уникальности данных на уровне приложения. Чаще всего это вопрос удаления повтора строк, т.к. именно этот тип данных является самым «ходовым» в случае работы с хранилищами. А где хранилища, там и кеши и вопрос о затратах памяти. И рано или поздно, в любой достаточно сложной системе кеширования встает вопрос дедупликации - хранить повторяющиеся строки уж очень дорого на больших обьемах данных.

Неофиты спросят: «а в чем проблема? Почему нельзя использовать обычный словарь под мьютексом?». И ведь правда, мы можем использовать тип map для хранения уникальных значений любых сравниваемых типов. По скорости, словарь из стандартной библиотеки, превзойдут только уж совсем специализированные словари, которые большинство писать никогда не будет. Однако у этого подхода есть один существенный, но критический вопрос: как удалять ключи которых больше нет в нашей системе?

В языках со сборщиком мусора, типо Java и C#, для решения этой проблемы есть специализированные типы (WeakHashMap, WeakSet) которые автоматически удаляют ключи, на которые никто больше не ссылается. Под капотом практически все они используют weak reference (слабая ссылка, если только она ссылается на переменную, то сборщик мусора имеет право собрать переменную). Однако разработчики компилятора Go активно сопротивляются внедрению слабых ссылок в язык. Причины тому разные, но основная мысль кроется в нежелании усложнять рантайм и сборщик мусора без «лишней» необходимости.

Однако если чему-то сопротивляться, это не значит, что в этом чем-то пропадет потребность. Модуль go4.org/intern содержит в себе реализацию такой системы дедупликации значений. Авторами этого пакета являются разработчики Tailscale, часть из которых либо являлись частью Go Core Team в прошлом, либо активно работали над Go компилятором извне. Сам модуль используется внутри inet.af/netaddr который, в свою очередь, тянут в том числе и большие проекты.

Недостаток у go4.org/intern один: написан он с очень большим процентом черной магии, часть из которой еще и сильно ненадежна. Настолько ненадежна, что создателям модуля пришлось сделать (и регулярно обновлять) дополнительный модуль go4.org/unsafe/assume-no-moving-gc единственная цель которого, это убедиться, что сборщик мусора в Go все еще не двигает объекты в памяти хипа.

Проблема стала настолько явной, что Михаэль Кнызэк (один из ключевых разработчиков рантайма Go) предложил решить проблему уже на уровне стандартной библиотеки. Дескать не дело это, что модуль от которого зависит примерно 0,1% всей экосистемы (что достаточно много), может работать только в текущей внутрянке Go. Да и на дженерики бы уже неплохо все перенести. Предложенное API достаточно простое: есть одна глобальная функция которая возвращает враппер вокруг переменной и гарантирует ее уникальность в памяти. Враппер же нужен для быстрого сравнения уникальных значений между собой. А вся магия будет скрыта внутри райнтайма, который самостоятельно будет удалять переменные на которых больше никто не ссылается.

На мой взгляд, это попытка в очередной раз отложить внедрение слабых ссылок, потребность в которых назрела и перезрела уже давно. Однако меня устроит и такой вариант развития событий, ибо уже лучше чем ничего или магия которая может в любой момент развалиться.
👍22
Go Update
Update: proposal: spec: add untyped builtin zero Собрав фидбек Расс предлагает немного изменить правила использования для zero: новый идентификатор можно будет использовать для присваивания и сравнения только там где недоступны другие «короткие» идентификаторы…
proposal: spec: add untyped builtin zero (closed)

Случилось неожиданное. Предложение было принято. А затем собрав фидбэк (среди которого высказался и Роб «наше все» Пайк) Расс принял решение отозвать предложенное изменение. И хотя с самим отзывом я в корне не согласен, я могу понять причины: «срач» в ветке не утихал ни на день, породил два контр-предложения и вызывал новые проблемы в объяснении Go механик новичкам.

Однако сам факт отзыва расстроил меня под двум причинам:
- После принятия предложения и нескольких страниц срача, Расс обьявил, что в отсутствии новой информации, решение о принятии изменено не будет. А затем спустя несколько дней, в течении которых срач все равно продолжился, предложение было отозвано без каких либо комментариев. Что подводит к неприятной мысли о том, что любое предложение можно заставить отозвать просто через продолжение спора в обсуждении.
- Go Core Team явно имело внутренние разговоры по этому вопросу, однако поделится ими они не посчитали нужным. На мой взгляд, сие идет против духа открытого ПО. Но так как по факту Go полностью владеет Google, то и Open Source у нас очень условный.

Итог: на одно изменение меньше в Go 1.22. Возможно это и к лучшему…
83😨3👍2
И немного позитива: sync: add Map.Clear method

Там верно заметили, что раз у нас теперь есть встроенная функция clear для очистки словарей и слайсов, то хорошо бы такое иметь для sync.Map. Разработчики Go согласились и предложение было принято без лишних слов. Ждем реализации в Go 1.22.
👍162
📝 Где посмотреть список изменений в будущем релизе.

Список изменений на следующий релиз всегда доступен на https://tip.golang.org

Для Go 1.21 это был https://tip.golang.org/doc/go1.21
Для Go 1.22 это есть https://tip.golang.org/doc/go1.22
Для Go 1.23 это будет https://tip.golang.org/doc/go1.23

Однако сама страничка появляется примерно на второй-третий месяц разработки версии, а настоящая актуализация данных начинается за месяц-два до самого релиза. Т.е. сейчас на страничке 1.22 еще многого нет из того, что точно попадет в релиз.
6👍5🔥2
🤔 О темпе выхода новостей на канале.

Наверное многие обратили внимание, что новости на канале стали выходить существенно реже (последняя новость была аж 19го сентября). На это есть три причины:

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

- 😕Обсуждении zero было довольно довольно долгим и по итогу контр-продуктивным. А затем предложение было закрыто без каких либо комментариев. Не скрою - на какое-то время это здорово пошатнуло мотивацию.

- 📁Последние три недели особых предложений по языку или стандартной библиотеке никто не высказывал. Вероятно все силы команды брошены на реализацию предложенных к 1.22 вещей. Плюс недавно прошел GopherCon 2023 на который команда на время переключилась.

По итогу я очень надеюсь продолжить выкладывать свои мысли по поводу эволюции языка, благо у меня еще есть список изменений которые стоит осветить. Весь вопрос лишь в силах на это всё…
90👍26👏1
🤗 Благодарность за поддержку прошлого сообщения.

Спасибо всем кто отписался и проставил позитивные emoji. Это ценно.
34👍6
🤨 proposal: spec: memoization (likely decline)

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

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

Go Core Team высказала те же опасения. Плюс добавили, что вопрос можно решить через сторонний пакет и дженерик тип, который позволит обобщить все работу по мемоизации (по аналогии как сейчас работает sync.Once и sync.OnceFunc).

Отсюда и вывод: предложение предлагают отклонить. Дали три недели на случай, если у кого-то найдутся серьезные аргументы в пользу принятия данного предложения.
👍19
⚙️ proposal: cmd/go: add support for dealing with flaky tests или работа с «капризными» тестами.

Нестабильные тесты – настоящий бич мира разработки ПО. Для тех немногих счастливчиков, кто не в курсе: "flaky tests" – это тесты, которые проходят или не проходят в зависимости от фазы луны. При повторном запуске такой тест, как правило, успешно проходит (как и при всех последующих попытках). В идеальном мире таких тестов в проекте быть не должно по определению. Однако реальность такова: такие тесты есть почти везде. Они есть у вас в проекте, они есть в Tailscale (где даже написали специальный враппер для работы с ними), они есть и в компиляторе Go.

Брэд Фитцпатрик предлагает решить эту проблему на уровне туллинга для языка. Вы помечаете тест как flaky, и go test автоматически понимает, что его нужно повторить (возможно, несколько раз) в случае ошибки. Предложение еще находится на ранних этапах обсуждения, поэтому у вас есть возможность поучаствовать и предложить свои идеи.
👍303👎2🔥1
🙄 go4.org/unsafe-assume-no-moving-gc: когда все равны, но некоторые равнее.

В модуле go4.org/unsafe/assume-no-moving-gc есть интересное место. В нём вызывается функция из рантайма Go с помощью go:linkname (управляющая директива в комментариях, которая позволяет вызывать приватные функции и методы из других пакетов) - heapObjectsCanMove. Функция крайне простая - пока GC не двигает объекты в хипе, она возвращает false. Если (когда) начнёт, то будет возвращать true.

Прикол в том, что эта функция появилась специально в Go 1.21 именно для этого модуля. А причина проста: без неё модуль assume-no-moving-gc надо было обновлять с каждой новой версией компилятора Go. Именно этим ребята и оправдывают включение этой приватной функции в пакет runtime.

И всё же приятно, когда твои бывшие коллеги работают над компилятором, который ты используешь в разработке своего продукта 😆.
👍7🗿6🤯1