А ещё планируем с Колей записать подкаст по поводу релиза 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
Я тут выступать подписался на 14ую Стачку в Питере. 2го октября на сей конференции, я буду рассказывать про интересное:
А еще мне как спикеру выдали промокод
П.С. Сентябрь дрянь. Квартира — инфекционный бокс уже третью неделю. Надеюсь, что дальше будет лучше.
Итераторы: не опять, а снова.
Расскажу про дизайн и эволюцию итераторов. Начну с того, как про них писали в "Паттернах проектирования" и какими были итераторы в Go 1.0. Как разработчики пришли к текущему дизайну "range-over-func", какие проблемы пришлось решить (почему переделали циклы for). Почему большинство Go разработчиков уже пишет итераторы, но еще не знает об этом. Расскажу про то, как это работает под капотом и насколько все хорошо/плохо с производительностью, почему итераторы это не только про скорость. И в заключении расскажу о том, как мы используем итераторы в MWS Cloud Platform и где их использовать не стоит.
А еще мне как спикеру выдали промокод
GOPHER10 - дающий скидку 10% на покупку билета. В общем если раздумывали о том, пойти или нет, то у вас есть еще один аргумент за.П.С. Сентябрь дрянь. Квартира — инфекционный бокс уже третью неделю. Надеюсь, что дальше будет лучше.
🔥22❤2
Go Update
❄️ runtime/secret: add new package: о тех кто застрял в лимбе. Как часто вы зануляете память? Подозреваю, что ответ большинства Go разработчиков будет где-то между "никогда" и "зачем?". И действительно, в большинстве приложений такая задача никогда не появляется.…
🔐runtime/secret: secret.Do 🔐
Тем временем, абсолютно буднично и рутинно произошло хорошее: пакет
Собственно весь пакет состоит из одной функции:
• Весь стек который использовался во время работы горутины заполняется нулями. Если при работе стек «рос» (по факту — копировался в новое место) то прямо во время копии старый участок памяти рантайм заполнит нулями.
• Все регистры ЦПУ которые «могут содержать секреты» будут заполнены нулями после выхода. Подозреваю, что здесь речь идет о регистрах которые не используются самим рантаймом для служебных действий (верх, низ стека и прочая).
• Если в процессе работы переданной функции мы создаем объекты в хипе, то сразу после сборки мусора, их память будет заполнена нулями.
• Если внутри передаваемой функции произошла паника, подменяют стектрейс, что-бы скрыть любую информацию о переданной функции.
Для большинства это изменение ничего не меняет.
Но для тех кто работает с криптографией (включая TLS которое мы все используем в HTTPS, HTTP/2 и gRPC без флага insecure) это хорошая новость, которая позволяет усилить защиту приложений и усложнить чтение секретов злонамеренными акторами, даже если скомпрометирована вся железка. Плюс «надежную» очистку секретов часто требуют при сертификации софта в разных регионах нашей планеты.
П.С. Пакет пока доступен только для архитектур
П.П.С. Так-же пока пакет работает только под Linux.
Тем временем, абсолютно буднично и рутинно произошло хорошее: пакет
runtime/secret получил свою реализацию и будет доступен в Go 1.26 (правда будет скрыт за флагом GOEXPERIMENT=runtimesecret устанавливаемым во время компиляции).Собственно весь пакет состоит из одной функции:
secret.Do, которая принимает на вход функцию с сигнатурой func() и подчищает за ней следующие вещи на выходе из этой функции:• Весь стек который использовался во время работы горутины заполняется нулями. Если при работе стек «рос» (по факту — копировался в новое место) то прямо во время копии старый участок памяти рантайм заполнит нулями.
• Все регистры ЦПУ которые «могут содержать секреты» будут заполнены нулями после выхода. Подозреваю, что здесь речь идет о регистрах которые не используются самим рантаймом для служебных действий (верх, низ стека и прочая).
• Если в процессе работы переданной функции мы создаем объекты в хипе, то сразу после сборки мусора, их память будет заполнена нулями.
• Если внутри передаваемой функции произошла паника, подменяют стектрейс, что-бы скрыть любую информацию о переданной функции.
Для большинства это изменение ничего не меняет.
Но для тех кто работает с криптографией (включая TLS которое мы все используем в HTTPS, HTTP/2 и gRPC без флага insecure) это хорошая новость, которая позволяет усилить защиту приложений и усложнить чтение секретов злонамеренными акторами, даже если скомпрометирована вся железка. Плюс «надежную» очистку секретов часто требуют при сертификации софта в разных регионах нашей планеты.
П.С. Пакет пока доступен только для архитектур
amd64 и arm64 (если вы не поняли, что это значит, это хорошо тк вы точно попадаете в доступные архитектуры).П.П.С. Так-же пока пакет работает только под Linux.
GitHub
runtime/secret: implement new secret package · golang/go@a3fb92a
Implement secret.Do.
- When secret.Do returns:
- Clear stack that is used by the argument function.
- Clear all the registers that might contain secrets.
- On stack growth in secret mode, clea...
- When secret.Do returns:
- Clear stack that is used by the argument function.
- Clear all the registers that might contain secrets.
- On stack growth in secret mode, clea...
🔥43❤5🤯1
Про go mod tidy | verify | download
Задумывались ли вы о том, как именно Go проверяет целостность ваших скаченных модулей? Как наш тулчейн проверяет, что зависимости которые вы видите в своем проекте, соответствуют зависимостям которые видят другие разработчики?
Я думаю, что нет, ибо работает простой принцип: работает — не трогай. Однако мне, по роду деятельности, пришлось залезть внутрь и прочитать (несколько раз) спеку и посмотреть реализацию. И для того, чтоб структурировать свои изыскания я пишу сей пост.
Все начинается с попытки получить модуль. После первого скачивания модуля (через вызов
• Сортирует имена файлов в архиве и пробегает
• Далее он сравнивает получившийся хеш с записью о зависимости которая хранится в
- Если модуль приватный (выставлены переменные окружения
- Если нет прокси для модулей (например вы берёте файлы напрямую с гита) то Go сам создает zip архив и помещает его в скаченное.
- Подсчет хеша архива модуля недешевая операция в общем смысле, особенно если её постоянно вызывать. Поэтому, кроме zip файла модуля мы рядом храним полученный хеш в файле c суффиксом
• Во время сборки бинаря наш компилятор, чтобы не терять время, не проверяет целостность архива и распакованных данных, а только сравнивает, что строчки в
И тут наступает вопрос: а как проверить, что никто не трогал наш кеш модулей? В дело вступает
• Сначала он читает хеш из
• Затем он читает и хеширует распакованные файлы модуля, сравнивая их итоговый хеш с полученным на прошлом этапе. Затем тоже самое повторяется для zip архива модуля. Операция аналогична тому, что происходит при скачивании.
• Если не совпало, то
Обратите внимание, что здесь
А что если мне подменили
• Во время скачивания предполагается, что между нами и БД хешсумм установленно защищенное соединение.
• Сама БД хешей, это даже не БД в общем смысле, а дерево, где каждый новый элемент зависит от прошлых вставок. Поэтому при попытке поменять запись развалятся записи о всех хешах модулей которые были вставлены после. Кому интересны подробности рекомендую вот эту статью https://research.swtch.com/tlog и погуглить
• Когда мы скачиваем хеш, мы получаем не отдельное значение, а некое «поддерево» хешей которое необходимо нам для валидации нашего модуля. Это дерево мы помещаем в
Задумывались ли вы о том, как именно Go проверяет целостность ваших скаченных модулей? Как наш тулчейн проверяет, что зависимости которые вы видите в своем проекте, соответствуют зависимостям которые видят другие разработчики?
Я думаю, что нет, ибо работает простой принцип: работает — не трогай. Однако мне, по роду деятельности, пришлось залезть внутрь и прочитать (несколько раз) спеку и посмотреть реализацию. И для того, чтоб структурировать свои изыскания я пишу сей пост.
Все начинается с попытки получить модуль. После первого скачивания модуля (через вызов
go mod tidy или go mod download на проекте) в формате zip архива с прокси для модулей, Go делает следующее• Сортирует имена файлов в архиве и пробегает
sha256 по каждому файлу. Получившийся набор пар "hash filepath" он прогоняет через sha256 еще раз, кодирует его в base64, добавляет префикс h1: и запоминает результат. В общем виде это выглядит как вызов вот такой команды:
sha256sum $(find . -type f | sort) | sha256sum
• Далее он сравнивает получившийся хеш с записью о зависимости которая хранится в
go.sum внутри вашего проекта. Если её нет (или нет go.sum, т.е. вы только начали проект) то он идет в GOSUMDB и спрашивает хеш у него. В обоих случаях, после совпадения хешей, zip файл модуля пишется в локальные загрузки ($GOPATH/pkg/mod/cache/download/<url>) и распаковывается в локальный кеш ($GOPATH/pkg/mod/cache/<url>). Если не совпало, ничего не пишем и кидаем ошибку. Побочный вывод — нельзя называть модуль cache или sumdb, о чем ниже.- Если модуль приватный (выставлены переменные окружения
GOPRIVATE и/или GONOSUMDB) или вообще отключена связь с сервером хешсумм через GOSUMDB=off, то проверять хешсумму он будет исключительно с тем, что есть в go.sum внутри проекта. Если там такого модуля нет, то мы доверяем полученным данным и добавляем полученную хешсумму в go.sum. - Если нет прокси для модулей (например вы берёте файлы напрямую с гита) то Go сам создает zip архив и помещает его в скаченное.
- Подсчет хеша архива модуля недешевая операция в общем смысле, особенно если её постоянно вызывать. Поэтому, кроме zip файла модуля мы рядом храним полученный хеш в файле c суффиксом
.ziphash.• Во время сборки бинаря наш компилятор, чтобы не терять время, не проверяет целостность архива и распакованных данных, а только сравнивает, что строчки в
go.sum проекта совпадают с тем, что у нас лежит в ziphash файлах.И тут наступает вопрос: а как проверить, что никто не трогал наш кеш модулей? В дело вступает
go mod verify, который пробегаясь по всем модулям из go.mod делает следующее:• Сначала он читает хеш из
ziphash файла.• Затем он читает и хеширует распакованные файлы модуля, сравнивая их итоговый хеш с полученным на прошлом этапе. Затем тоже самое повторяется для zip архива модуля. Операция аналогична тому, что происходит при скачивании.
• Если не совпало, то
verify кидает ошибку на модуль и выходит.Обратите внимание, что здесь
go.sum проекта нигде не участвует. Проверяется целостность именно кеша.А что если мне подменили
ziphash вместе с файлами модуля и zip архивом? На это есть ряд ответов:• Во время скачивания предполагается, что между нами и БД хешсумм установленно защищенное соединение.
• Сама БД хешей, это даже не БД в общем смысле, а дерево, где каждый новый элемент зависит от прошлых вставок. Поэтому при попытке поменять запись развалятся записи о всех хешах модулей которые были вставлены после. Кому интересны подробности рекомендую вот эту статью https://research.swtch.com/tlog и погуглить
Merkle Tree.• Когда мы скачиваем хеш, мы получаем не отдельное значение, а некое «поддерево» хешей которое необходимо нам для валидации нашего модуля. Это дерево мы помещаем в
$GOPATH/pkg/mod/cache/download/sumdb/ (тот самый) и используем для проверки локального модуля. И тут происходит интересное: если удалить ziphash файл то даже без соединения с интернетом, go mod download сможет восстановить хеши из частей большого дерева лежащих в $GOPATH/pkg/mod/cache/download/sumdb/ и записать их обратно в ziphash.👍16❤4🤯3🔥1
Про go mod tidy | verify | download (Part 2)
Получается, что на практике подделать запись (или случайно закараптить модуль) довольно сложно, тк проверка идет из нескольких мест. Однако потенциальная атака существует:
• Атакующий может переписать модуль, его архив и
• Затем атакующий переписывает хеш внутри
• Тогда, даже если вы перед сборкой делаете
Проблема этой атаки заключается в том, что стоит вам вычистить
Получается, что на практике подделать запись (или случайно закараптить модуль) довольно сложно, тк проверка идет из нескольких мест. Однако потенциальная атака существует:
• Атакующий может переписать модуль, его архив и
ziphash файлы.• Затем атакующий переписывает хеш внутри
go.sum ваших проектов.• Тогда, даже если вы перед сборкой делаете
go mod download и go mod verify, то компилятор не заподозрит подмену.Проблема этой атаки заключается в том, что стоит вам вычистить
ziphash файлы из кеша и вся эта схема разваливается. Одна сложность — отдельной команды я под это не нашел, но в качестве замены можно взять следующую команду
find $GOPATH/pkg/mod/cache/ -type f -name "*.ziphash" | xargs -rn1 rm
🔥4❤3👍1🗿1
Forwarded from Thank Go! (Anton Zhiyanov)
Интерактивный тур по Go 1.26
Опубликовал традиционный тур по будущему релизу (на англ). Часть фич мы с вами уже разобрали, а часть еще разберем, но если хотите прочитать все вместе уже сейчас — добро пожаловать.
Вот что вошло:
— new(expr)
— Безопасная проверка ошибок
— Новый «чайный» GC
— Ускоренный cgo и выделение памяти
— SIMD для amd64
— Секретный режим
— Криптография без ридеров
— Профиль для ловли утекающих горутин
— Метрики состояния горутин
— Итераторы в reflect
— Подсматривание в байтовый буфер
— Дескриптор процесса ОС
— Сигнал как причина в контексте
— Сравнение IP-подсетей
— Dialer с контекстом
— Фальшивый example.com
— Оптимизированные fmt.Errorf и io.ReadAll
— Множественные хендлеры в логах
— Артефакты тестов
— Обновленный go fix
Это жесть сколько всего они в релиз запихнули 😅
https://antonz.org/go-1-26
Опубликовал традиционный тур по будущему релизу (на англ). Часть фич мы с вами уже разобрали, а часть еще разберем, но если хотите прочитать все вместе уже сейчас — добро пожаловать.
Вот что вошло:
— new(expr)
— Безопасная проверка ошибок
— Новый «чайный» GC
— Ускоренный cgo и выделение памяти
— SIMD для amd64
— Секретный режим
— Криптография без ридеров
— Профиль для ловли утекающих горутин
— Метрики состояния горутин
— Итераторы в reflect
— Подсматривание в байтовый буфер
— Дескриптор процесса ОС
— Сигнал как причина в контексте
— Сравнение IP-подсетей
— Dialer с контекстом
— Фальшивый example.com
— Оптимизированные fmt.Errorf и io.ReadAll
— Множественные хендлеры в логах
— Артефакты тестов
— Обновленный go fix
Это жесть сколько всего они в релиз запихнули 😅
https://antonz.org/go-1-26
🔥17❤3✍2
Антон традиционно публикует список нововведений которые приедут к нам с Go 1.26. Самое интересное это
new(…expr…), pprof для ловли утечки горутин и обновленный go fix. Рекомендую ознакомится, тем более всё представлено в интерактивном виде.Telegram
Thank Go!
Здравый взгляд на язык программирования Go.
Злой админ @nalgeon. Добрый админ @mikeberezin. Рекламы нет.
Злой админ @nalgeon. Добрый админ @mikeberezin. Рекламы нет.
🔥3
🚀️️️️️️ proposal: spec: direct reference to embedded fields in struct literals 🚀️️️️️️
Embedding структур часто используется как некая «замена наследованию», для того что-бы объединить общий код для нескольких типов внутри одного встраиваемого типа. Это довольно удобно, тк вместе с полями мы получаем еще и методы структуры, при этом обращаться к ним можно как через имя встроенной структуры, так и напрямую. Например
Однако «символьная» инициализация подобной структуры всегда требовала полный синтаксис:
Читается сие, на мой взгляд, довольно сложно. Есть и другая проблема: такую методику «выноса» нельзя использовать как рефакторинг, ведь мы ломаем инициализацию у пользователей нашего кода. Этим озаботились и сами разработчики компилятора Go, и предложили разрешить обращаться к полям встроенной структуры, как к родным в момент инициализации. Т.е. В будущем можно будет писать и так:
Правда есть одно но: а что делать если встроена не структура, а указатель? Кидать панику? Делать «неявную» аллокацию для встроенного указателя? А если таких «встроек» несколько?
Из-за потенциальной (и множественной) сложности выводов, на данный момент, принято решение разрешить новый синтаксис инициализации только для полей-значений. Т.е. код
как и раньше, не скомпилируется. На мой взгляд, это хорошее решение.
Статус issue: likely accept, а значит есть все шансы увидеть новый синтаксис в Go 1.27.
П.С. Само предложение датируется аж 2015ым. Похоже Go Team основательно взяла курс на разгребание старых проблем.
Embedding структур часто используется как некая «замена наследованию», для того что-бы объединить общий код для нескольких типов внутри одного встраиваемого типа. Это довольно удобно, тк вместе с полями мы получаем еще и методы структуры, при этом обращаться к ним можно как через имя встроенной структуры, так и напрямую. Например
type E struct {
A int
}
type T struct {
E
}
var v T
v.E.A = 100
println(v.A)
Однако «символьная» инициализация подобной структуры всегда требовала полный синтаксис:
v := T{E: E{A: 1}}
Читается сие, на мой взгляд, довольно сложно. Есть и другая проблема: такую методику «выноса» нельзя использовать как рефакторинг, ведь мы ломаем инициализацию у пользователей нашего кода. Этим озаботились и сами разработчики компилятора Go, и предложили разрешить обращаться к полям встроенной структуры, как к родным в момент инициализации. Т.е. В будущем можно будет писать и так:
v := T{A: 1}
Правда есть одно но: а что делать если встроена не структура, а указатель? Кидать панику? Делать «неявную» аллокацию для встроенного указателя? А если таких «встроек» несколько?
Из-за потенциальной (и множественной) сложности выводов, на данный момент, принято решение разрешить новый синтаксис инициализации только для полей-значений. Т.е. код
type F struct {
*E
}
v := F{A: 100}
как и раньше, не скомпилируется. На мой взгляд, это хорошее решение.
Статус issue: likely accept, а значит есть все шансы увидеть новый синтаксис в Go 1.27.
П.С. Само предложение датируется аж 2015ым. Похоже Go Team основательно взяла курс на разгребание старых проблем.
GitHub
proposal: spec: direct reference to embedded fields in struct literals · Issue #9859 · golang/go
(Status: referred from LanguageChange to Proposal. --adonovan) Consider type E struct { A int } type T struct { E } This works: T{E: E{A: 1}} This does not: T{A: 1} Makes some struct literals more ...
👍13