Об обсуждениях.
Вот уже более тринадцати лет нормальный синтаксис неподвижно обсуждается на GitHub.
По воле отцов-основателей выступает Повелитель Простоты и правит миллионами микросервисов благодаря мощи своего неисчислимого бойлерплейта.
Он — гниющий реликт минимализма, в ком незримые муки разработчиков продлеваются загадочными отказами «это не вписывается в философию».
Он — незыблемый столп экосистемы, которому каждый день приносят в жертву тысячи бестолковых предложений о try-catch, идиотские идеи которых были озвучены уже десятки раз, а все самопротиворечащие доводы высказаны и рассмотрены.
На боли и страданиях гоферов стоит тот самый "Idiomatic Go"
Вы знаете, что такое безумие?
Кто-то скажет, что факт того, что язык получивший свой релиз в 2012-ом году, но не имевший дженериков аж до 2022го — это безумие. На что можно резонно возразить: дескать, нормальный синтаксис — это полдела, основная проблема в экосистеме! Другие могут сказать, что почти все реализации (включая и ту, которую в итоге получили мы) обладают рядом минусов и требуется их хорошо продумать, перед тем как вносить этот инструмент в язык. Третьи скажут, что внесение дженериков в язык привлекает вниманиеC++ любителей всё усложнять, а сам Go был ценен в первую очередь простотой и понятливостью даже свежему после универа программисту. Короче: оправданий можно придумать массу. На самом деле доподлинно никто не знает, почему внедрение дженериков заняло так много времени, поэтому любые попытки найти рациональное объяснение — не более чем «игра для ума» (по-простому — ещё один способ вентиляции лёгких), которая не несёт в себе никакой практической пользы.
Нет, скажу я вам. Безумие это хождение по кругу годами в поисках идеального синтаксиса который устроит всех. Например, обсуждение синтаксиса лямбд, которое ведётся уже более 8 лет и которое, по итогу, так и не сдвинулось с места. Синтаксиса! Не семантики и не деталей реализации. Ибо главный выбор, который остался перед нами, — это то, «будет ли новый синтаксис использовать
Честно — у меня нет цензурных слов. Если вам когда-нибудь хотелось узнать, что такое "Bikeshedding" (в русском языке нет прямого перевода, но термин расшифровывается как «бессмысленное обсуждение тривиальных вопросов»), то это обсуждение — самый наглядный пример, который у меня есть. Где-то полгода назад, когда, как мне казалось, картинка начала выкристаллизовываться, я хотел написать об этом запись в блоге. И попросить людей поучаствовать, если им есть что высказать или подсказать, ведь это шанс поучаствовать в развитии языка, а создатели действительно слушают мнение людей по этому вопросу! Теперь я понимаю — первый раз за долгое время меня спасло то, что я что-то не сделал. Ибо с тех пор, несмотря на как минимум два резюме по итогам «ещё одной итерации обсуждения», продвижения по-прежнему нет.
Я не знаю, какой здесь сделать вывод. Но я уверен, что нас ждёт ещё минимум столько же комментариев в будущем.
In the grim darkness of the far future there is only "
Вот уже более тринадцати лет нормальный синтаксис неподвижно обсуждается на GitHub.
По воле отцов-основателей выступает Повелитель Простоты и правит миллионами микросервисов благодаря мощи своего неисчислимого бойлерплейта.
Он — гниющий реликт минимализма, в ком незримые муки разработчиков продлеваются загадочными отказами «это не вписывается в философию».
Он — незыблемый столп экосистемы, которому каждый день приносят в жертву тысячи бестолковых предложений о try-catch, идиотские идеи которых были озвучены уже десятки раз, а все самопротиворечащие доводы высказаны и рассмотрены.
На боли и страданиях гоферов стоит тот самый "Idiomatic Go"
Вы знаете, что такое безумие?
Кто-то скажет, что факт того, что язык получивший свой релиз в 2012-ом году, но не имевший дженериков аж до 2022го — это безумие. На что можно резонно возразить: дескать, нормальный синтаксис — это полдела, основная проблема в экосистеме! Другие могут сказать, что почти все реализации (включая и ту, которую в итоге получили мы) обладают рядом минусов и требуется их хорошо продумать, перед тем как вносить этот инструмент в язык. Третьи скажут, что внесение дженериков в язык привлекает внимание
Нет, скажу я вам. Безумие это хождение по кругу годами в поисках идеального синтаксиса который устроит всех. Например, обсуждение синтаксиса лямбд, которое ведётся уже более 8 лет и которое, по итогу, так и не сдвинулось с места. Синтаксиса! Не семантики и не деталей реализации. Ибо главный выбор, который остался перед нами, — это то, «будет ли новый синтаксис использовать
=>, или ->, а может, \-> для разделения объявления и тела лямбды?». И если кто-то думает, что я шучу, то ему достаточно глянуть issue, в котором уже больше 900 скрытых комментариев, по которым уже несколько раз делали сводку (вручную, с помощью Gabby, с помощью других LLM, комбинацией из трёх прошлых способов) и которое раз за разом возвращается назад, к своему началу. К выбору идеального синтаксиса. К безумию.Честно — у меня нет цензурных слов. Если вам когда-нибудь хотелось узнать, что такое "Bikeshedding" (в русском языке нет прямого перевода, но термин расшифровывается как «бессмысленное обсуждение тривиальных вопросов»), то это обсуждение — самый наглядный пример, который у меня есть. Где-то полгода назад, когда, как мне казалось, картинка начала выкристаллизовываться, я хотел написать об этом запись в блоге. И попросить людей поучаствовать, если им есть что высказать или подсказать, ведь это шанс поучаствовать в развитии языка, а создатели действительно слушают мнение людей по этому вопросу! Теперь я понимаю — первый раз за долгое время меня спасло то, что я что-то не сделал. Ибо с тех пор, несмотря на как минимум два резюме по итогам «ещё одной итерации обсуждения», продвижения по-прежнему нет.
Я не знаю, какой здесь сделать вывод. Но я уверен, что нас ждёт ещё минимум столько же комментариев в будущем.
In the grim darkness of the far future there is only "
if err != nil".GitHub
proposal: spec: short function literals · Issue #21498 · golang/go
[edit: As of today, end of May 2025, this proposal has received ~1000 comments. Please read the summary before adding more comments. Your ideas may have been discussed already. Thanks.] [edit: As o...
❤12👍4🔥2👀2🗿1
⏲️ testing/synctest — останавливаем время ⏲️
Одними из самых сложных сценариев для тестирования являются сценарии где замешано время. Если использовать реальное время то тесты либо а) начинают занимать слишком много времени либо б) теряют в надежности из-за гонки "кода со временем". Особенно хорошо это ощущается в тестах которые используют
Приведу очень простой пример:
Для того, что-бы убедиться, что наш код выведет "do work..." 4 раза нам нужно подождать примерно 2 секунды, в течении которых наша программа фактически ничего не делает. Более того, нет никаких гарантий, что наш текст будет выведен именно 4 раза, а не 3 или 2 с учетом нагрузки на планировщик ОС.
Когда такой тест у нас один это нормально. Когда у нас их десятки это проблема. А когда у нас их за сотню то это минуты простаивающего CI, который мог бы делать что-то полезное. И тут у нас есть два решения:
• В пределах тестов кратно уменьшить время "ожидания". Допустим не 500мс а 50. Или вообще 5мс. Проблема такого подхода в том, что исполнение (и работа планировщика) тоже занимает время и тест становится менее надежным. При этом проблема "впустую потраченного времени" никуда не уходит.
• Используем одну из сторонних библиотек для "подделки" времени и замыкаемся на ее семантику (и баги) по всей программе.
Кроме того, оба способа еще приводят к необходимости пробрасывать параметры (время, или сам мок работы со временем) через всю программу, что усложняет чтение кода.
Хорошая новость, что разработчики языка озаботились это проблемой, и в Go 1.25 пакет
Первая это
• Блокирующая попытка посылки или получения данных из канала созданного в том же "пузыре".
•
• Вызов
•
Однако следующие операции не приводят к "прочной блокировке" горутин:
• Лок мьютексов.
• Блокировка на операциях ввода-вывода (файлы, сеть и прочая).
• Сисколлы.
Вторая функция это
Таком образом как только все горутины "прочно заблокированы" происходит одно из следующих:
• Если
• В противном случае время внутри "пузыря" сдвигается на достаточную величину для запуска в работу хотя-бы одной горутины если функция создававшая "пузырь" не закончила исполнение.
• В противном случае, происходит дедлок и наш вызов
Проще всего понять на живом примере (код не влез в этот пост). Обратите внимание, что время выставлено в часы однако время теста и порядок вывода в лог сохраняется раз за разом. Так мы обеспечиваем не только быстрое исполнение, но и ожидаемый детерминизм. Другой плюс нового пакета, заключается в том, что если горутина создавшая "пузырь" выйдет до того, как закончат работу все её дочерние горутины, то вы получите панику (пример). Таким образом на этапе тестирования еще и обеспечивается контроль очистки ресурсов.
Для более подробной документации рекомендую глянуть документацию. Там-же приведены и другие примеры, сценарии и особенности работы.
Одними из самых сложных сценариев для тестирования являются сценарии где замешано время. Если использовать реальное время то тесты либо а) начинают занимать слишком много времени либо б) теряют в надежности из-за гонки "кода со временем". Особенно хорошо это ощущается в тестах которые используют
time.Ticker, time.Timer и time.AfterFunc для управление потоком исполнения.Приведу очень простой пример:
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
for {
select {
case <-time.After(500 * time.Millisecond):
println("do work...")
case <-ctx.Done():
println("Context done:", ctx.Err())
}
}
Для того, что-бы убедиться, что наш код выведет "do work..." 4 раза нам нужно подождать примерно 2 секунды, в течении которых наша программа фактически ничего не делает. Более того, нет никаких гарантий, что наш текст будет выведен именно 4 раза, а не 3 или 2 с учетом нагрузки на планировщик ОС.
Когда такой тест у нас один это нормально. Когда у нас их десятки это проблема. А когда у нас их за сотню то это минуты простаивающего CI, который мог бы делать что-то полезное. И тут у нас есть два решения:
• В пределах тестов кратно уменьшить время "ожидания". Допустим не 500мс а 50. Или вообще 5мс. Проблема такого подхода в том, что исполнение (и работа планировщика) тоже занимает время и тест становится менее надежным. При этом проблема "впустую потраченного времени" никуда не уходит.
• Используем одну из сторонних библиотек для "подделки" времени и замыкаемся на ее семантику (и баги) по всей программе.
Кроме того, оба способа еще приводят к необходимости пробрасывать параметры (время, или сам мок работы со временем) через всю программу, что усложняет чтение кода.
Хорошая новость, что разработчики языка озаботились это проблемой, и в Go 1.25 пакет
synctest стал наконец доступен любому желающему. Публичное API содержит всего две функции:Первая это
synctest.Test. Она запускает замыкание в изолированном пространстве-пузыре где время течёт "иначе". Все горутины созданные внутри этого замыкания разделяют этот "пузырь". Время в них стоит на месте, до тех пор пока все горутины не станут "прочно заблокированы". Термин "прочно заблокированы" может прозвучать странно, но по сути это лишь определенный набор блокировок которые приводят к сдвигу времени в "пузыре». Вот их полный список:• Блокирующая попытка посылки или получения данных из канала созданного в том же "пузыре".
•
select с блокирующими операциями над каналами созданным в том же "пузыре".• Вызов
sync.Cond.Wait или time.Sleep.•
sync.WaitGroup.Wait, если sync.WaitGroup.Add был вызван из того же "пузыря" (не горутины, это важно).Однако следующие операции не приводят к "прочной блокировке" горутин:
• Лок мьютексов.
• Блокировка на операциях ввода-вывода (файлы, сеть и прочая).
• Сисколлы.
Вторая функция это
synctest.Wait(). Ее единственная роль — дождаться момента когда все горутины в "пузыре" достигли "прочной блокировки" и затем вернуться.Таком образом как только все горутины "прочно заблокированы" происходит одно из следующих:
• Если
Wait был вызван, то он возвращается. Время не сдвигается.• В противном случае время внутри "пузыря" сдвигается на достаточную величину для запуска в работу хотя-бы одной горутины если функция создававшая "пузырь" не закончила исполнение.
• В противном случае, происходит дедлок и наш вызов
Test паникует.Проще всего понять на живом примере (код не влез в этот пост). Обратите внимание, что время выставлено в часы однако время теста и порядок вывода в лог сохраняется раз за разом. Так мы обеспечиваем не только быстрое исполнение, но и ожидаемый детерминизм. Другой плюс нового пакета, заключается в том, что если горутина создавшая "пузырь" выйдет до того, как закончат работу все её дочерние горутины, то вы получите панику (пример). Таким образом на этапе тестирования еще и обеспечивается контроль очистки ресурсов.
Для более подробной документации рекомендую глянуть документацию. Там-же приведены и другие примеры, сценарии и особенности работы.
go.dev
Go Playground - The Go Programming Language
👍11🔥3
Go Update
⏲️ testing/synctest — останавливаем время ⏲️ Одними из самых сложных сценариев для тестирования являются сценарии где замешано время. Если использовать реальное время то тесты либо а) начинают занимать слишком много времени либо б) теряют в надежности из…
А теперь по простому:
Этот код не закончит исполнение в ближайший год.
А этот код закончит исполнение менее чем за микросекунду и всегда выведет сначала "inside goroutine" а потом "outside goroutine".
func TestTime(t *testing.T) {
time.Sleep(365 * 24 * time.Hour)
go func() {
println("inside goroutine")
time.Sleep(time.Second)
}()
println("outside goroutine")
time.Sleep(time.Second)
}Этот код не закончит исполнение в ближайший год.
func TestTime(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
time.Sleep(365 * 24 * time.Hour)
go func() {
println("inside goroutine")
time.Sleep(time.Second)
}()
synctest.Wait()
println("outside goroutine")
time.Sleep(time.Second)
})
}А этот код закончит исполнение менее чем за микросекунду и всегда выведет сначала "inside goroutine" а потом "outside goroutine".
❤17👍4
🛡️ Go 1.25: встроенная защита от CSRF в net/http 🛡️
Тем временем разработчики стандартной библиотеки продолжают упрощать нам жизнь. Практически всё кто связаны с вебразработкой слышали про атаку CSRF. Суть в том, что используя форму (и не только) злонамеренный сайт может заставить ваш браузер выполнить, например, перевод денег из банка на другой счёт, если у банка нет защиты от CSRF, а у вас в этот момент действующая кука от ЛК банка.
Я не буду касаться описания принципов работы "same site" и "same origin", так как про это написано уже масса статей, а коснусь лишь основных механизмов защиты от CSRF:
• Вместе с кукой присылать скрытый
• Проверять через заголовок
• SameSite куки и "Non-simple requests" которые защищают от вариантов атаки HTTP -> HTTPS но в общем случае бесполезны.
На данный момент для защиты от CSRF в нашей экосистеме есть две либы: csrf и nosurf. Обе работают через дубль токена (т.е. требуют донастройки фронта) и обе почти не поддерживаются разработчиками.
Поэтому Go 1.25 в пакет
Заголовок с сайта банка при запросе через fetch в таком случае будет выглядеть так:
В то время как заголовок от зловредного сайта при «прямой» подгрузке будет выглядеть вот так
Сам proposal добавляет лишь один тип
Как это работает:
• Браузер добавляет
• В случае если дополнительно установлен список ориджинов через метод
• Запросы без
• «Безопасные» методы
Для более сложных случаев предусмотрены методы
Тем временем разработчики стандартной библиотеки продолжают упрощать нам жизнь. Практически всё кто связаны с вебразработкой слышали про атаку CSRF. Суть в том, что используя форму (и не только) злонамеренный сайт может заставить ваш браузер выполнить, например, перевод денег из банка на другой счёт, если у банка нет защиты от CSRF, а у вас в этот момент действующая кука от ЛК банка.
Я не буду касаться описания принципов работы "same site" и "same origin", так как про это написано уже масса статей, а коснусь лишь основных механизмов защиты от CSRF:
• Вместе с кукой присылать скрытый
<input> в котором присылать дубль токена, который идет в самой куке. Если при запросе то, что в форме и то, что в куке не совпало — запрос отклоняется. Недостаток в том, что токен надо привязывать к пользователю и добавлять в каждую форму.• Проверять через заголовок
Origin что инициатор запроса был сам исходный сайт, а не сторонний. Тоже обладает рядом минусов (может быть null при кривых плагинах), и требует довольно сложной настройки для правильной поддержки cross-origin запросов.• SameSite куки и "Non-simple requests" которые защищают от вариантов атаки HTTP -> HTTPS но в общем случае бесполезны.
На данный момент для защиты от CSRF в нашей экосистеме есть две либы: csrf и nosurf. Обе работают через дубль токена (т.е. требуют донастройки фронта) и обе почти не поддерживаются разработчиками.
Поэтому Go 1.25 в пакет
net/http добавили готовую «прослойку» для защиты от CSRF, построенную на механизме Fetch Metadata который присутствует во всех современных браузерах с 2023го года. Заголовок с сайта банка при запросе через fetch в таком случае будет выглядеть так:
GET /money/foo.json
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
В то время как заголовок от зловредного сайта при «прямой» подгрузке будет выглядеть вот так
GET /money/cool.jpg
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: image
Сам proposal добавляет лишь один тип
CrossOriginProtection, который предназначен для оборачивания ваших обработчиков.Как это работает:
• Браузер добавляет
Sec-Fetch-Site (same-origin / same-site / cross-site / none). Хендлер смотрит это заголовок, и если это не same-origin или none а метод это POST/PUT/PATCH/DELETE то запрос режется. Тоже самое если нет Sec-Fetch-Site: тогда смотрим Origin и сравниваем с Host и опять же, в случае несовпадения, режем POST/PUT/PATCH/DELETE запросы.• В случае если дополнительно установлен список ориджинов через метод
AddTrustedOrigin то полученный запрос сравнивается по заголовку Origin пока не будет найдет нужный, или запрос не будет отклонен.• Запросы без
Sec-Fetch-Site и без Origin пропускаются тк их явно не мог сделать браузер, защищать нечего.• «Безопасные» методы
GET/HEAD/OPTIONS всегда пропускаются (уповают на то, что вы не меняете состояние в этих методах и следуете разумным практикам)Для более сложных случаев предусмотрены методы
AddInsecureBypassPattern и функция SetDenyHandler которая явно разрешает запрос.MDN Web Docs
Cross-site request forgery (CSRF) - Security | MDN
In a cross-site request forgery (CSRF) attack, an attacker tricks the user or the browser into making an HTTP request to the target site from a malicious site. The request includes the user's credentials and causes the server to carry out some harmful action…
👍16❤5
Осталось написать (и разобраться) про новый экспериментальный сборщик мусора и программа минимум будет закрыта 😄
👍17❤6😁2
Go Update
🎂 Тем временем Земля сделала полный оборот вокруг Солнца, и мне исполнилось 32. В этот раз буду предельно краток: я жив, у меня всё хорошо, и этот блог не заброшен. Единственное, чего мне пока очень сильно не хватает, — это времени. Заметок скопилось за три…
🎂 Настал тот день когда мне исполнилось 33!
Да, да тот самый год, в который вас поздравляют используя аналогии к одной из самых ярких личностей в истории человечества 😁️️️️️️.
В (не)далеком детстве, когда мне было лет 7-8, я смотрел на взрослых, которым было за 30 (что казалось мне очень-очень далеко), и она казались кем-то, кто такой «опытный, мудрый, знающий». Думал, что вот: вырасту я, и сам буду такой взрослый-серьезный-мудрый. Машину водить, детей воспитывать. В очках ходить.
И вот теперь мне за 30. Я вожу машину (иногда даже две). Я воспитываю сына. Я хожу в очках (что кстати минус). И вот, что я вам скажу: хрень это все про «вырастишь, сам поймешь!». Фраза пустышка, которую так любили повторять родители и старшие близкие в процессе воспитания, но которая ничего под собой не имеет. Я не чувствую себя опытнее. Или мудрее. Или более знающим. Я ничего так и не «понял». Из года в год я надеюсь, что настанет тот самый магический момент когда я стану наконец «взрослым» (и хотя-бы перестану влезать в бессмысленные споры в чатике которые могут съесть час в лучшем случае). Но этот момент всё никак не настаёт.
Тем более последние годы здорово перевернули жизнь, а рождение сына, два года назад, вообще заставило взглянуть на себя по новому. Но вот сказать, что я теперь я стал весь из себя такой «мудрый-разумный» я не могу. В душе мне по прежнему кажется, что я ментально застрял где-то в возрасте 17-19 лет. Я по прежнему смотрю на своих друзей и вижу в них школьников а не серьезных дядь, коими я видел взрослых будучи мелким. При фразе «пропусти дядю!» я по прежнему оглядываюсь, пытаясь найти того самого «дядю». А вот единственное чего с годами становится объективно меньше это время, и как следствие сил. И то просто из-за количества рутинных дел которые приходится делать день за днём. Та вещь фундаментально непонятна когда тебе 8 и времени хватает на всё и даже больше.
В общем тут уже идет пятый параграф и надо бы начать подводить итоги. И вот мой итог на следующий год: надо нормально спать. Наверное это самая важная мудрость, которую я никак не могу постигнуть. Если вам между 18 и 28-30, то знайте, что «ремонт сбитого режима, за два дня, без регистрации и смс» это не навсегда. Я пишу эти строки сонный, ибо лёг поздно (пункт про время), а в 5 утра меня поднял сын «кики мама не, кики папа мими да!», что в переводе означало что «ему хочется кефир, а мама просыпаться отказалась». Пока просыпался-вставал-наливал-ждал-укладывал сон слетел и пришлось укладывать еще и себя (что гораздо дольше). В общем на сегодня сделал вывод, что на следующий ночной сон пойду вместе с ним. Но вот вечером я вероятно опять найду оправдание в голове, что-бы этого не делать…
Какой уж тут «опытный, мудрый, знающий» если банальный сон привести в порядок не можешь.
П.С. Статья про новый сборщик мусора делается, надеюсь успеть до релиза Go 1.25.
Да, да тот самый год, в который вас поздравляют используя аналогии к одной из самых ярких личностей в истории человечества 😁️️️️️️.
В (не)далеком детстве, когда мне было лет 7-8, я смотрел на взрослых, которым было за 30 (что казалось мне очень-очень далеко), и она казались кем-то, кто такой «опытный, мудрый, знающий». Думал, что вот: вырасту я, и сам буду такой взрослый-серьезный-мудрый. Машину водить, детей воспитывать. В очках ходить.
И вот теперь мне за 30. Я вожу машину (иногда даже две). Я воспитываю сына. Я хожу в очках (что кстати минус). И вот, что я вам скажу: хрень это все про «вырастишь, сам поймешь!». Фраза пустышка, которую так любили повторять родители и старшие близкие в процессе воспитания, но которая ничего под собой не имеет. Я не чувствую себя опытнее. Или мудрее. Или более знающим. Я ничего так и не «понял». Из года в год я надеюсь, что настанет тот самый магический момент когда я стану наконец «взрослым» (и хотя-бы перестану влезать в бессмысленные споры в чатике которые могут съесть час в лучшем случае). Но этот момент всё никак не настаёт.
Тем более последние годы здорово перевернули жизнь, а рождение сына, два года назад, вообще заставило взглянуть на себя по новому. Но вот сказать, что я теперь я стал весь из себя такой «мудрый-разумный» я не могу. В душе мне по прежнему кажется, что я ментально застрял где-то в возрасте 17-19 лет. Я по прежнему смотрю на своих друзей и вижу в них школьников а не серьезных дядь, коими я видел взрослых будучи мелким. При фразе «пропусти дядю!» я по прежнему оглядываюсь, пытаясь найти того самого «дядю». А вот единственное чего с годами становится объективно меньше это время, и как следствие сил. И то просто из-за количества рутинных дел которые приходится делать день за днём. Та вещь фундаментально непонятна когда тебе 8 и времени хватает на всё и даже больше.
В общем тут уже идет пятый параграф и надо бы начать подводить итоги. И вот мой итог на следующий год: надо нормально спать. Наверное это самая важная мудрость, которую я никак не могу постигнуть. Если вам между 18 и 28-30, то знайте, что «ремонт сбитого режима, за два дня, без регистрации и смс» это не навсегда. Я пишу эти строки сонный, ибо лёг поздно (пункт про время), а в 5 утра меня поднял сын «кики мама не, кики папа мими да!», что в переводе означало что «ему хочется кефир, а мама просыпаться отказалась». Пока просыпался-вставал-наливал-ждал-укладывал сон слетел и пришлось укладывать еще и себя (что гораздо дольше). В общем на сегодня сделал вывод, что на следующий ночной сон пойду вместе с ним. Но вот вечером я вероятно опять найду оправдание в голове, что-бы этого не делать…
Какой уж тут «опытный, мудрый, знающий» если банальный сон привести в порядок не можешь.
П.С. Статья про новый сборщик мусора делается, надеюсь успеть до релиза Go 1.25.
🔥45❤24👏3
Go Update
🎉 Вышел Go 1.24! 🎉 Этот момент настал! Ключевые нововведения: — Дженерики теперь умеют в псевдонимы (aliases) т.е. теперь можно писать так type MyType[T any] = myType[T,*T] Поздравляю тех, кому приходилось работать с указателями в дженериках, теперь…
🎉 Вышел Go 1.25! 🎉
Пока я не успел статью про новый сборщик мусора написать, поэтому быстро пробегусь по основным нововведениям которых не касался в прошлых записях.
— ♻️ Бинарей в комплекте теперь меньше. Разработчики компилятора активно использовать команду
— Новая директива
— Когда go команда обновляет
—
— 🍵 Новый экспериментальный сборщик мусора. О нем статья будет позже.
— 🔀️️️️️️ Новый тип
— 🛠 Компилятор теперь генерирует дебаг-инфу в формате DWARF5. Практический итог: бинари едят меньше места и быстрее комбинируются.
— 🏎️️️️️️ Новый экспериментальный пакет
— Тип
— 🏎️️️️️️ Функция
— Директива
—
— Новый метод
— 🔥
Читать про релиз вот тут.
Пока я не успел статью про новый сборщик мусора написать, поэтому быстро пробегусь по основным нововведениям которых не касался в прошлых записях.
— ♻️ Бинарей в комплекте теперь меньше. Разработчики компилятора активно использовать команду
go tool у себя внутри, что убирает необходимость поставлять заготовки в комплекте. Но как минимум go build и go test бинари все еще на месте.— Новая директива
ignore в go.mod. Подробное описание тут. Если в вкратце: для этого вы раньше использовали каталог testdata и каталоги которые начинаются с точки.— Когда go команда обновляет
go 1.xx.y директиву в go.mod она больше не добавляет toolchain директиву.—
go vet теперь ругается на неправильное использование sync.WaitGroup.Add и fmt.Sprintf("%s:%d", host, port) ибо есть net.JoinHostPort.— 🍵 Новый экспериментальный сборщик мусора. О нем статья будет позже.
— 🔀️️️️️️ Новый тип
runtime/trace.FlightRecorder позволяет записывать только значимые события, а не всё подряд для tracing’га (под капотом используется циклический буфер, который помнит N последних секунд).— 🛠 Компилятор теперь генерирует дебаг-инфу в формате DWARF5. Практический итог: бинари едят меньше места и быстрее комбинируются.
— 🏎️️️️️️ Новый экспериментальный пакет
encoding/json/v2. По хорошему про него тоже надо писать отдельную статью, но если в кратце — он намного быстрее того что было внутри encoding/json. А другая хорошая новость заключается в том, что если вы включили GOEXPERIMENT=jsonv2 то больше ничего менять не надо, так как encoding/json сам подключит новую внутряку.— Тип
os.Root приобрел несколько новых методов.— 🏎️️️️️️ Функция
reflect.TypeAssert позволяет приводить типы из reflect.Value в конкретный тип, минуя потенциально аллоцирующий вызов reflect.Value.Interface.— Директива
GODEBUG=checkfinalizers=1 позволяет понять, как дела в вашей очереди cleanup’ов и finalizer’ов во время каждого GC.—
SetDefaultGOMAXPROCS позволяет сбросить настройки GOMAXPROCS если вдруг переменная прилетела через Env или через прошлый вызов GOMAXPROCS.— Новый метод
sync.WaitGroup.Go - больше нет необходимости тащить errgroup если вам не нужен был возврат ошибок и отмена контекста.— 🔥
testing.T/B/F теперь имеют метод Output() io.Writer который позволяет правильно редиректить вывод внутри вызова теста.Читать про релиз вот тут.
go.dev
Go Modules Reference - The Go Programming Language
🔥26✍3❤3👍2
А ещё планируем с Колей записать подкаст по поводу релиза 1.25 где у вас будет возможность задать все интересующие вас вопросы. Вероятно объяснение нового сборщика мусора будет в первую очередь там (с помощью пальцев и активной жестикуляции).
Так что следите за анонсами 😁.
Статья здесь все равно будет, если вы не переносите видео.
Так что следите за анонсами 😁.
Статья здесь все равно будет, если вы не переносите видео.
Telegram
Николай Тузов
Go Developer, автор YouTube канала по Go: https://www.youtube.com/@nikolay_tuzov
Live канал: @ntuzov_live
Интересные подборки по Go: @golang_digest
Обратная связь: @justskiv
Поддержать:
https://boosty.to/nikolay.tuzov/
https://t.iss.one/ntuzov/126
Live канал: @ntuzov_live
Интересные подборки по Go: @golang_digest
Обратная связь: @justskiv
Поддержать:
https://boosty.to/nikolay.tuzov/
https://t.iss.one/ntuzov/126
❤17🔥10😐1
Forwarded from Николай Тузов
https://youtube.com/live/VHjXHzs742c?feature=share
Когда: в ближайшую субботу, 23 августа, 11:00 по Мск
Обсуждаем тем же составом, которым обсуждали когда-то Go v1.21:
- Николай Тузов
- Глеб Яльчик
- Дмтрий Матрёничев
А пока ждёте, советую почитать посты Димы на эту тему, у него очень подробные и крутые разборы
#gogetpodcast #go_1_25
Please open Telegram to view this post
VIEW IN TELEGRAM
Youtube
- YouTube
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
🔥7
Я только сейчас понял, что у нас снова, за долгое время, совпали цифры релиза и года. Причем впервые совпали обе цифры. В последний раз это был Go 1.6 и совпала только последняя.
Таймлайн:
Таймлайн:
go1.0 2012-03-28
go1.1 2013-05-13
go1.2 2013-12-01
go1.3 2014-06-18
!go1.4 2014-12-10
!go1.5 2015-08-19
!go1.6 2016-02-17
go1.7 2016-08-15
go1.8 2017-02-16
go1.9 2017-08-24
go1.10 2018-02-16
go1.11 2018-08-24
go1.12 2019-02-25
go1.13 2019-09-03
go1.14 2020-02-25
go1.15 2020-08-11
go1.16 2021-02-16
go1.17 2021-08-16
go1.18 2022-03-15
go1.19 2022-08-02
go1.20 2023-02-01
go1.21 2023-08-08
go1.22 2024-02-06
go1.23 2024-08-13
go1.24 2025-02-11
!go1.25 2025-08-12🔥21👍6🤯5💩2
👁Визуализатор нашего трехцветного сборщика мусора.
Сегодня на подкасте я упомянул, что у нас трехцветный сборщик мусора. Для меня, как человека, который привык разбирать вещи «на практике или в действии» самым лучшим объяснением выступил визуализатор от ребят из Pusher который они сделали в рамках своей своей статьи про его особенности. И хотя статье уже почти 8 лет, ничего из основ, которые в нее положены, с тех пор не поменялось. В общем: очень и очень рекомендую.
Так-же есть хорошая статья про сборщик мусора от Авито (хотя секция про Write Barrier довольно тяжела для восприятия) и цикл статей от Ardan Labs о основах памяти и о том как правильно читать выводы рантайма про сборку мусора.
Сегодня на подкасте я упомянул, что у нас трехцветный сборщик мусора. Для меня, как человека, который привык разбирать вещи «на практике или в действии» самым лучшим объяснением выступил визуализатор от ребят из Pusher который они сделали в рамках своей своей статьи про его особенности. И хотя статье уже почти 8 лет, ничего из основ, которые в нее положены, с тех пор не поменялось. В общем: очень и очень рекомендую.
Так-же есть хорошая статья про сборщик мусора от Авито (хотя секция про Write Barrier довольно тяжела для восприятия) и цикл статей от Ardan Labs о основах памяти и о том как правильно читать выводы рантайма про сборку мусора.
🔥29
🚀 Расширение функции
Отличные новости! Предложение, обсуждение которого которого длится уже больше четырех лет и которое выдвинул сам Роб Пайк, наконец-топодходит к принятию приняли!
В чем суть: есть у нас встроенная функция
Однако у оператора "
И вот теперь, спустя 13 лет после релиза языка, нас ждет камбэк функции
А сие значит, чтовероятно точно уже в 1.26 можно будет избавится от хелперов, таких как:
Маленькое, но давно назревшее изменение, принятию которого (пускай и в слегка измененной версии) рад даже сам Пайк.
new для создания указателя на значения 🚀Отличные новости! Предложение, обсуждение которого которого длится уже больше четырех лет и которое выдвинул сам Роб Пайк, наконец-то
В чем суть: есть у нас встроенная функция
new, которая принимает тип и возвращает указатель на значение этого типа. Хорошая функция, однако исторически так сложилось, что она была в тени оператора "&" который использовался и для создания указателей на комплексные типы и для взятия адреса существующих переменных. С учетом того, что для создания словарей, каналов и срезов используется функция make, прикладного постоянного использования у new было немного.Однако у оператора "
&" тоже есть недостатки. Самый явный — он не умеет работать со значениями примитивов (т.е. нельзя сделать a := &1, такой код просто не скомпилируется). Другая проблема в том, что для продолжения работы с указателем, в месте его взятия, нам нужно помещать выражение в скобочки. Т.е. нельзя написать &myComplexType{}.CallStuff() но можно написать (&myComplexType{}).CallStuff().И вот теперь, спустя 13 лет после релиза языка, нас ждет камбэк функции
new так как ее новый синтаксис будет принимать как типы, так и значения. Текущее предложение делает корректным вот такий синтаксис:…
a := new(123)
b := new(myConstant)
c := new(int64(-123))
…
А сие значит, что
func ptrTo[V any](v V) *V { return &v }Маленькое, но давно назревшее изменение, принятию которого (пускай и в слегка измененной версии) рад даже сам Пайк.
GitHub
spec: expression to create pointer to simple types · Issue #45624 · golang/go
(Latest proposal at #45624 (comment); --adonovan) This notion was addressed in #9097, which was shut down rather summarily. Rather than reopen it, let me take another approach. When &S{} was ad...
❤46🔥28👍18
Тут появилась запись нашего подкаста где мы обсуждали 1.25. Получилось довольно неплохо, как и говорил — поводил руками при объяснении нового сборщика мусора. Ну и про другие вещи не забыли.
❤2👍2🔥1
Forwarded from Николай Тузов
https://youtu.be/fHuJNsZPCJ0
Дима был очень хорош, такого подробного разбора новой версии вы больше нигде не увидите, а с комментариями Глеба оно ещё круче, очень рекомендую.
Напоминаю, что теперь я буду выкладывать новые выпуски подкаста на отдельном канале, чтобы не смешивать столь разный контент.
- Досмотривайте выпуски до конца
- Подписывайтесь на канал
- Ставьте лайки
- Делитесь с друзьями и коллегами
Это правда очень важно.
Несмотря на скромные показатели, я всё же возобновил регулярные выпуски, как вы могли заметить. Потому что хороших подкастов по Go сейчас практически нет, и кто-то ведь должен этим заниматься
Очень надеюсь на вашу поддержку.
#gogetpodcast #news
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Go v1.25 — Глубокий разбор всех изменений | GoGetPodcast №17
Подробно обсудили - что добавилось в новой версии Go 1.25, зачем всё это нужно, как с этим работать.
Go 1.25 Release Notes: https://tip.golang.org/doc/go1.25
Состав:
- Николай Тузов
- Глеб Яльчик
- Дмтрий Матрёничев, ведёт шикарный ТГ-канал по Go: http…
Go 1.25 Release Notes: https://tip.golang.org/doc/go1.25
Состав:
- Николай Тузов
- Глеб Яльчик
- Дмтрий Матрёничев, ведёт шикарный ТГ-канал по Go: http…
❤11🔥7👍2
🏗️ gogrep — инструмент для семантического поиска внутри вашей кодовой базы. 🏗️
Наверняка много кому приходилось сталкиваться с ситуацией «надо по коду найти вызовы по определенному паттерну». Чаще всего для этого мы используем регулярные выражения (grep, ag, rg). Однако у них всех есть один минус — они интерпретируют файлы как текст, а не как код. Из-за этого в результаты поиска попадают как нужные нам места вызова, так и комментарии, участки текста и прочая.
Решение этой проблемы: семантический поиск. Это когда утилита разбивает файл на синтаксическое дерево и производит поиск уже по самому дереву. Приведу простой пример:
Здесь мы явно говорим: найди все вызовы, у которых слева есть идентификатор
Документация по gogrep доступна тут. С описанием синтаксиса немного сложнее: большую (и лучшую) часть информации по мэтчингу и по фильтрам можно найти в тестах. Сама тулза является часть куда более мощной тулзы go-ruleguard (которая кстати входит в golangci-lint).
За обе утилиты огромнейшее спасибо Искандеру Шарипову.
Наверняка много кому приходилось сталкиваться с ситуацией «надо по коду найти вызовы по определенному паттерну». Чаще всего для этого мы используем регулярные выражения (grep, ag, rg). Однако у них всех есть один минус — они интерпретируют файлы как текст, а не как код. Из-за этого в результаты поиска попадают как нужные нам места вызова, так и комментарии, участки текста и прочая.
Решение этой проблемы: семантический поиск. Это когда утилита разбивает файл на синтаксическое дерево и производит поиск уже по самому дереву. Приведу простой пример:
~/mws/api > gogrep . 'ptr.Get($_)'
Здесь мы явно говорим: найди все вызовы, у которых слева есть идентификатор
ptr а внутри вызова идет только один аргумент (не важно выражение, их сумма, или переменная). Таким образом мы идентифицируем именно конкретные места которые будут частью компилируемого кода.Документация по gogrep доступна тут. С описанием синтаксиса немного сложнее: большую (и лучшую) часть информации по мэтчингу и по фильтрам можно найти в тестах. Сама тулза является часть куда более мощной тулзы go-ruleguard (которая кстати входит в golangci-lint).
За обе утилиты огромнейшее спасибо Искандеру Шарипову.
GitHub
GitHub - quasilyte/gogrep: Syntax-aware Go code search, based on the mvdan/gogrep
Syntax-aware Go code search, based on the mvdan/gogrep - quasilyte/gogrep
❤14👍6
Go Update
🏗️ gogrep — инструмент для семантического поиска внутри вашей кодовой базы. 🏗️ Наверняка много кому приходилось сталкиваться с ситуацией «надо по коду найти вызовы по определенному паттерну». Чаще всего для этого мы используем регулярные выражения (grep,…
Тут мне справедливо заметили, что есть и другие утилиты подобного толка, которые и умеют больше и языков поддержка у них шире. Соглашусь. Для исторической правды приведу те, которые известны лично мне:
• semgrep — один из старейших инструментов статического анализа. Поддерживает больше 30 языков, имеет GUI, поддерживает файл с комплексными правилами и вообще комбайн. Недостаток только один: для использования некоторого функционала нужна коммерческая лицензия. Рекомендую глянуть набор правил (часть написана на ruleguard о котором ниже) от Дэмиена Граски для понимания всех возможностей которые может данная утилита.
• opengrep — после того как ребята ответственные с утилиту из прошлого пункта решили переехать на коммерческие рельсы, коллектив из нескольких AppSec команд форкнул проект и продолжил развивать его самостоятельно. Умеет почти все (и даже больше), что умеет semgrep, и весь функционал абсолютно бесплатный.
• ast-grep — относительный новичок в поле поиска по паттерну в AST. Написан на Rust. Поддерживает трансформацию кода и меньше, чем прошлые две утилиты, ориентирован на поиск проблем с безопастностью.
При всех плюсах вышестоящих утилит, для меня главный их минус в их универсальности. Для каждой из них Go не является основным языком, что ограничивает мощности паттернов по поиску и трансформации. Более того, ruleguard (который частично/полностью основан на gogrep) поддерживает возможность написания трансформаторов кода (автоматический рефакторинг) на Go, а значит не нужно учить и запоминать еще один синтаксис. Плюс из коробки у нас интеграция с
• semgrep — один из старейших инструментов статического анализа. Поддерживает больше 30 языков, имеет GUI, поддерживает файл с комплексными правилами и вообще комбайн. Недостаток только один: для использования некоторого функционала нужна коммерческая лицензия. Рекомендую глянуть набор правил (часть написана на ruleguard о котором ниже) от Дэмиена Граски для понимания всех возможностей которые может данная утилита.
• opengrep — после того как ребята ответственные с утилиту из прошлого пункта решили переехать на коммерческие рельсы, коллектив из нескольких AppSec команд форкнул проект и продолжил развивать его самостоятельно. Умеет почти все (и даже больше), что умеет semgrep, и весь функционал абсолютно бесплатный.
• ast-grep — относительный новичок в поле поиска по паттерну в AST. Написан на Rust. Поддерживает трансформацию кода и меньше, чем прошлые две утилиты, ориентирован на поиск проблем с безопастностью.
При всех плюсах вышестоящих утилит, для меня главный их минус в их универсальности. Для каждой из них Go не является основным языком, что ограничивает мощности паттернов по поиску и трансформации. Более того, ruleguard (который частично/полностью основан на gogrep) поддерживает возможность написания трансформаторов кода (автоматический рефакторинг) на Go, а значит не нужно учить и запоминать еще один синтаксис. Плюс из коробки у нас интеграция с
go/build, go/ast, go/tokens и go/types что позволяет получить всю мощь Go инструментария не выходя за пределы утилиты.GitHub
GitHub - semgrep/semgrep: Lightweight static analysis for many languages. Find bug variants with patterns that look like source…
Lightweight static analysis for many languages. Find bug variants with patterns that look like source code. - semgrep/semgrep
👍9🔥3❤1👏1
Go Update
Опросы в канале, да или нет? Там ко мне пришли с рекламой с предложением разместить опрос. Я обычно никакие опросы никогда сам не прохожу (кроме Go Developer Survey), поэтому оставляю решение за аудиторией. Как проголосуете, так и будем делать. П.С. Рекламы…
Есть такая старинная мудрость, о которой я регулярно забываю: «Никогда не говори Никогда». Ибо приходиться потом стыковать неидеальную жизнь с идеалистичными заявлениями. Тем более я никогда не думал, что мой бред мои очерки будет читать почти три тысячи человек.
За более чем два года, с момента цитируемого сообщения, ко мне приходило достаточно большое число людей (и гораздо больше чем я вообще ожидал) с разными предложениями: от продажи канала, до интеграций с разными площадками. Большинство (включая продажу) я отклоняю сразу без вопросов — если бы я делал блог на продажу, я бы не делал его таким личным. Большинство рекламных сообщений я так-же отклоняю, потому как считаю неразумным размещать вещи в которых я не уверен, ради относительно небольшого дохода. Сюда же идёт любой инструментарий для автоматического размещения рекламы. Да и текущая активность канала приведет к тому, что доля рекламы быстро приблизиться к негуманным «один-к-одному» и читать станет невозможно. Любые интеграции я оставляю на подумать, но мне никогда не хватает времени, что-бы к ним потом вернуться 😁️️️️️️.
Что подводит нас к маленькому, но важному: есть небольшой процент вещей, за которые я готов вписаться или которые мне интересны, и которые я готов тут размещать. При обязательном условии, что они попадают под тематику канала. Более того, технически я уже нарушал своё же правило: когда размещал объявления о своих выступления на других конференциях и/или подкастах.
Поэтому, в целях прозрачности, с сегодняшнего дня я думаю немного изменить вышестоящее правило:
1. Я буду рассказывать про те вещи (конференции, подкасты, митапы, курсы и прочее) за которые я готов «вписаться». Сюда входят мероприятия, в которых либо я сам принимаю участие (хоть и не организовываю), либо организаторы являются людьми в которых я уверен.
2. Я так-же возможно буду рассказывать про вещи которые мне интересны и могут быть интересны читателям. Сюда идут конференции и инструменты про которые я либо знаю-слышал, либо знаю «через кого-то» и они обладают достаточной степенью доверия, но вписаться за кого я дать не готов.
«А зачем что-то менять?» последует логичный вопрос. На мой взгляд существует ряд вещей которые находятся на стыке с тематикой этого канала и которые могут быть потенциально интересны тем кто меня читает.
Притом ко всем записям по прежнему останутся открытые комментарии: если пойдет какой-то откровенный шлак, то об этом всегда можно будет написать своё «фи». Но я очень надеюсь, что до этого не дойдёт, ибо меня сильно радует, что более чем у 20 процентов моих подписчиков включены уведомления о новомпотоке бреда сообщении в канале.
За более чем два года, с момента цитируемого сообщения, ко мне приходило достаточно большое число людей (и гораздо больше чем я вообще ожидал) с разными предложениями: от продажи канала, до интеграций с разными площадками. Большинство (включая продажу) я отклоняю сразу без вопросов — если бы я делал блог на продажу, я бы не делал его таким личным. Большинство рекламных сообщений я так-же отклоняю, потому как считаю неразумным размещать вещи в которых я не уверен, ради относительно небольшого дохода. Сюда же идёт любой инструментарий для автоматического размещения рекламы. Да и текущая активность канала приведет к тому, что доля рекламы быстро приблизиться к негуманным «один-к-одному» и читать станет невозможно. Любые интеграции я оставляю на подумать, но мне никогда не хватает времени, что-бы к ним потом вернуться 😁️️️️️️.
Что подводит нас к маленькому, но важному: есть небольшой процент вещей, за которые я готов вписаться или которые мне интересны, и которые я готов тут размещать. При обязательном условии, что они попадают под тематику канала. Более того, технически я уже нарушал своё же правило: когда размещал объявления о своих выступления на других конференциях и/или подкастах.
Поэтому, в целях прозрачности, с сегодняшнего дня я думаю немного изменить вышестоящее правило:
1. Я буду рассказывать про те вещи (конференции, подкасты, митапы, курсы и прочее) за которые я готов «вписаться». Сюда входят мероприятия, в которых либо я сам принимаю участие (хоть и не организовываю), либо организаторы являются людьми в которых я уверен.
2. Я так-же возможно буду рассказывать про вещи которые мне интересны и могут быть интересны читателям. Сюда идут конференции и инструменты про которые я либо знаю-слышал, либо знаю «через кого-то» и они обладают достаточной степенью доверия, но вписаться за кого я дать не готов.
«А зачем что-то менять?» последует логичный вопрос. На мой взгляд существует ряд вещей которые находятся на стыке с тематикой этого канала и которые могут быть потенциально интересны тем кто меня читает.
Притом ко всем записям по прежнему останутся открытые комментарии: если пойдет какой-то откровенный шлак, то об этом всегда можно будет написать своё «фи». Но я очень надеюсь, что до этого не дойдёт, ибо меня сильно радует, что более чем у 20 процентов моих подписчиков включены уведомления о новом
👍35😐1
✔️ errors.AsType — типобезопастная замена errors.As ✔️
Тем временем, в 1.26 нас (вероятно) ждет еще одно приятное изменение: дженерики наконец доберутся до пакета errors.
Все изменение проще описать тремя строчками кода. В 1.25 у нас вот так:
А в 1.26 можно будет вот так:
Вроде и небольшое изменение, но оно ведет, как минимум, к двум положительным вещам:
• Зона видимости типизированной ошибки во многих участках у нас теперь будет меньше, а значит меньше захламляется пространство имен и снижается необходимость думать над правильным именем для ошибки.
• В отличии от errors.As, который вторым аргументом принимал
Кстати, причина по которой сигнатура текущей функции выглядит как
компиляцию не пройдет. А причина в том, что интерфейсы у нас это отдельная сущность которая существует не только во время компиляции, но и во время выполнения.
Тем временем, в 1.26 нас (вероятно) ждет еще одно приятное изменение: дженерики наконец доберутся до пакета errors.
Все изменение проще описать тремя строчками кода. В 1.25 у нас вот так:
var pe *fs.PathError
if errors.As(err, &pe) {
fmt.Println("Failed at path:", pe.Path)
}
А в 1.26 можно будет вот так:
if pe, ok := errors.AsType[*fs.PathError](err); ok {
fmt.Println("Failed at path:", pe.Path)
}
Вроде и небольшое изменение, но оно ведет, как минимум, к двум положительным вещам:
• Зона видимости типизированной ошибки во многих участках у нас теперь будет меньше, а значит меньше захламляется пространство имен и снижается необходимость думать над правильным именем для ошибки.
• В отличии от errors.As, который вторым аргументом принимал
any, новая функция принимает только тех, кто реализует интерфейс error. Несмотря на то, что у нас есть проверка внутри go vet проверяющая второй аргумент у As, всегда приятнее когда компилятор может самостоятельно поймать ошибку на этапе сборки приложения.Кстати, причина по которой сигнатура текущей функции выглядит как
As(err error, target any) bool заключается в том, что указатель на интерфейс и указатель на тип реализующий интерфейс для компилятора две несовместимые конструкции. Иначе говоря, вот такой код
func As(err error, target *error) bool {
panic("unimplemented")
}
…
pe *fs.PathError
if As(err, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
}
…
компиляцию не пройдет. А причина в том, что интерфейсы у нас это отдельная сущность которая существует не только во время компиляции, но и во время выполнения.
GitHub
errors: AsType (As with type parameters) · Issue #51945 · golang/go
Currently in 1.18 and before, when using the errors.As method, an error type you would like to write into must be predeclared before calling the function. For example: var myErr *MyCustomError if e...
👍24🤮7🔥4❤1