Pro безопасность
Развитие языка неизбежно ведёт к увеличению уязвимостей и дефектов. Сегодня поговорим про инструменты безопасности, малоизвестную особенность языка Go и предотвращение состояния гонки. На закуску — новый фреймворк Bud для разработки веб-приложений.
Как рулить уязвимостями
В сентябре команда безопасности языка Go выпустила интересную статью про управление уязвимостями. Вот на что в ней стоит обратить внимание. В первую очередь — это база данных уязвимостей. Она представляет собой компиляцию уязвимостей Go, размещенных в общедоступных базах, таких как CVE и GHSA.
Также туда вносятся все подтверждённые уязвимости, о которых сообщили мейнтейнеры. Если вы сами обнаружили уязвимость в любимом языке — не поленитесь о ней сообщить. Обновление существующих записей производится через эту форму.
Кроме этого существует утилита govulncheck, которую можно включить в любой проект буквально двумя командами:
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
Она проверяет вашу кодовую базу и сообщает обо всех релевантных уязвимостях. Предполагается, что в будущем её включат в основной дистрибутив языка.
Как сломать чужой Open source
Помощь проектам с открытым исходным кодом — дело благое и всячески одобряемое сообществом. Но и тут есть шанс облажаться и довести до инфаркта напугать своими действиями разработчиков. Одну такую историю рассказал Эмре Савджи (Emre Savcı), старший разработчик в Trendyol и энтузиаст Open Source.
Всё началось с проекта swaggo/swag. Его часто используют в Go-проектах для автоматического создания документации API через обработку комментариев. Инструмент просматривает файлы проекта и строит дерево абстрактного синтаксиса для обеспечения навигации.
В одном из своих проектов автор статьи хотел ограничить парсинг только областью видимости функции-обработчика. Он предложил свой собственный PR в swaggo/swag. Код был проверен на работоспособность юнит-тестами и отправлен в проект. Здесь и начались неприятности.
Другие пользователи swaggo/swag получили ошибки в своих CI/CD конвейерах и при ручной генерации. Тут начинается самое интересное: при «разборе полётов» выяснилась малоизвестная особенность языка.
Оказывается, можно связать определение функции с определениями функций других пакетов при помощи директивы go:linkname и в итоге определить функцию без определения тела. Само существование такой «зверушки» автор статьи не мог себе представить. Логично же, что если мы определили функцию, то фактически определили и её тело. Но оказалось, что в Go одно не следует из другого. Такая функция крашилась с ошибкой нулевого указателя при попытке использовать её внутри цикла for.
Cоветуем прочитать эту статью и всегда помнить, что юнит-тесты вовсе не гарантия правильной работы кода. Хорошим подспорьем будет end-to-end тестирование. И не стоит пренебрегать проверками на нулевой указатель. Даже гипотетическими.
Потоко-безопасные пакеты
«…safety is number one priority» — это не только коронная фраза одного из популярных ютуберов, но и важное правило при разработке на Go. Например, при работе HTTP-сервера для каждого соединения создаётся отдельная горутина, выполняемая в одном адресном пространстве с другими.
Это, с одной стороны, хорошо, так как работает асинхронно. А с другой, делает возможной конкуренцию за одни и те же данные между ними. И когда одна горутина пытается записать, а другая в то же время считать одни и те же данные — случится конфуз паника.
Такое явление называется состоянием гонки (data race) и представляет серьёзную проблему при проектировании многопоточных систем. Увы, но без дополнительного флага --race при выполнении тестов эта проблема не выявляется. Советуем задействовать этот флаг во всех ваших проектах.
Горутины != потоки. В отличие от тяжёлых и медленных потоков ОС, горутины спроектированы быть легковесными и более эффективными. Переключение между потоками в операционной системе — достаточно сложный процесс. А внедрение защиты от аппаратных уязвимостей Spectre и Meltdown сделали его ещё сложнее и медленнее. У горутин же есть собственный планировщик, который позволяет разработчикам не думать о традиционных потоках.
Обеспечение потокобезопасности начинается со структуры будущего пакета. В нём стоит заранее определить начальные типы, методы, функции и комментарии. После создания структуры можно написать тесты. Понятное дело, что пока нет логики, они работать не будут. Но по ходу разработки всё больше тестов станут завершаться успешно. Такой подход часто используется при рефакторинге.
Далее есть смысл описать логику и продумать, как правильно использовать мьютексы. Если мы храним файлы в директории, то штатно нет возможности обеспечить им блокировку. Но можно встроить мьютексы в директорию. Как результат — получить экземпляры всех методов и функций, что и мьютекс. Это даст возможность задействовать Lock() и обеспечить для горутины эксклюзивный доступ к данным.
Монопольный доступ — лишь один из возможных приёмов обеспечения потокобезопасности кода. Чтобы узнать больше и взглянуть на примеры, советуем прочитать статью Making Golang Packages Thread-safe.
Full stack web-framework для Go
Веб-приложения чаще всего разрабатываются при помощи фреймворков. Для Python — это Flask или Django, для Ruby — Rails или Grape. Сегодня расскажем об одном из таких фреймворков для Go.
Знакомьтесь — очень молодой, но перспективный проект Bud, развязавший отличную дискуссию на HackerNews. Серверный рендеринг осуществляется через JS и чем-то напоминает Laravel, только для Go.
Одна из целей Bud — предоставить разработчикам высокоуровневые, типобезопасные API-интерфейсы, используя самые сильные стороны Go. Весь фреймворк — один бинарник, в котором будет содержаться всё необходимое для запуска. Это удобно, поскольку не требует установки Go на сервере. Традиционно пожелаем разработчику удачи! Если идея понравилась — не поленитесь поставить звёздочку на GitHub или принять участие в разработке.
Подкасты
Немного IT
Видеоподкаст, который снимают и развивают двое наших коллег из Evrone. Темы касаются языка Go — обсуждение его преимуществ и недостатков, сравнение с другими языками, с которыми ребятам приходилось работать.
Если вам есть что сказать или интересно послушать мнение со стороны о разработке на Go — добро пожаловать в комментарии!
Митапы и конференции
Ruby Russia
Программа уже доступна на официальном сайте — регистрируйтесь и присоединяйтесь к нашей онлайн-конференции 30 сентября и 1 октября.
Полторы тысячи рубистов, заранее отснятые в студии доклады кинематографического качества и прямой эфир из Сколково: всё, чтобы собраться и обсудить интересующие вас темы из мира Ruby разработки!
Осенний Go Meetup
19 октября 2022
Рады сообщить, что мы запланировали проведение Go Meetup. Его программа формируется, но регистрация уже открыта.
Детальная информация о мероприятии будет опубликована позже, следите за наши новостями. Если у вас есть идея доклада и вы хотите стать спикером, то пишите на почту andy@evrone.com.
Вакансии
Evrone
Мы открыты для новых Go-разработчиков. В Evrone можно работать удалённо с первого дня, мы поддерживаем и оплачиваем участие в Open-source проектах и выступления на конференциях, а расти в грейдах можно с помощью честной системы проверки навыков и менторства.