Да, sqlc отличный инструмент, но это разные весовые категории :-)
sqlc парсит SQL, генерирует Go-структуры и методы. Даёт типобезопасность, но добавляет шаг сборки, зависимость от внешнего тула и генерируемый код в репозиторий.
Мой же подход сейчас - это просто парсер на условно 50 строк кода. Ноль зависимостей, ноль генерации, полный контроль над кодом репозитория. Ты сам решаешь как сканировать результаты, какие хелперы использовать, как обрабатывать ошибки.
В целом считаю sqlc отличным интснтументом. Если нужна типобезопасность и не смущает кодогенерация, sqlc это одно из лучших решений, тут сложно спорить. Если хочешь минимализм и полный контроль, то вполне хватит простого go:embed с парсером. Иногда (да по правде говоря чаще всего), этого вполне достаточно.
Хороший разработчик не привязывается к одному инструменту, а понимает компромиссы каждого.
Хранимые процедуры легитимный подход, но со своими компромиссами. Логика размазывается между приложением и БД. Для меня это усложняет отладку и понимание системы целиком.
Версионирование процедур отдельная боль. Нужно синхронизировать миграции БД с деплоем приложения.
Тестирование тоже усложняется. Для unit-тестов репозитория теперь нужна реальная БД с актуальными процедурами. Плюс vendor lock-in: PL/pgSQL !== T-SQL !== MySQL процедуры.
Странно что Не бойся использовать разные инструменты в одном проекте при чтении статьи проходит мимо глаз. Если у вас команда DBA сильная и процедуры стандарт, отлично. Embedded SQL для тех, кто хочет держать всю логику в Go и деплоить одним бинарником.
Константы в Go-файле - валидный подход. Но в чистом .sql файле работает полноценный SQL-тулинг: форматирование через pg_format, линтинг через sqlfluff, автодополнение колонок при подключении IDE к БД.
Парсер и риск ошибок. Регулярка тривиальная, 5 строк. Если разработчик забудет маркер, запрос не попадёт в map, и Get() упадёт с panic при первом же вызове. Ошибка не пройдёт незамеченной.
Ошибка компиляции. Тут я возможно действительно преувеличил. go:embed даст ошибку компиляции только если файл не найден. Однако никто кто мешает прикрутить нормальную валидацию SQL при инициализации пакета. Все это выходит на рамки простой статьи.
Как я писал в самом начали в конце статьи: это не единственный, да и не самый лучший способ организации работы с SQL файлами. Однако в большинстве случаев на моей практике он самый удобный.
Евгений спасибо, полезная статья! Было бы неплохо также детальнее разобрать мьютексы и библиотеку race (то как она работает под капатом). Думаю получился бы неплохой цикл статей по примитивам синхронизации.
В тексте ошибка. Generics - это функции или типы, которые могут работать с любым типом данных. В Go generics были введены в версии 1.21 и они означают, что вы можете написать функцию, которая будет работать с любым типом данных, а не только с определенным.
При написании пути можно использовать ~ для обозначения директории пользователя системы. По умочанию vscode складывает свои настройки в ~/.vscode. Я этого в описании не писал, сейчас напишу. Заодно лого поменяю, а то неудачное какое-то получилось )
Кстати сделал. В версии 2.1.3 можно выделить текст в коде и на основе него создать компонент по шаблону. Более того, в названии компонента поддерживаются конструкции типа ../. Указав название шаблона как "../../modals/register user", расширение выйдет на 2 уровня вверх, создаст директорию modals и в нее положит компонент.
Прекрасная идея подтягивать сниппеты с GitHub Gist, однако он не сильно подходит для шаблонов, так как нельзя создавать директории! Но темнеменее в задачи записал :)
Тут все упирается в гибкость. Для каждого языка и фреймворка есть существует архитектура компонентов. Про реакт вообще молчу. Для этого придется создавать под каждый фреймворк отдельное расширение :)
Что касается не dumb ускорения, тут согласен. Все упирается в идеи. На момент реализации расширения, для меня нынешняя реализация была максимально удобной.
В какой-то степени статья больше нужна для сбора идей.
Да, sqlc отличный инструмент, но это разные весовые категории :-)
sqlc парсит SQL, генерирует Go-структуры и методы. Даёт типобезопасность, но добавляет шаг сборки, зависимость от внешнего тула и генерируемый код в репозиторий.
Мой же подход сейчас - это просто парсер на условно 50 строк кода. Ноль зависимостей, ноль генерации, полный контроль над кодом репозитория. Ты сам решаешь как сканировать результаты, какие хелперы использовать, как обрабатывать ошибки.
В целом считаю sqlc отличным интснтументом. Если нужна типобезопасность и не смущает кодогенерация, sqlc это одно из лучших решений, тут сложно спорить. Если хочешь минимализм и полный контроль, то вполне хватит простого
go:embedс парсером. Иногда (да по правде говоря чаще всего), этого вполне достаточно.Хороший разработчик не привязывается к одному инструменту, а понимает компромиссы каждого.Интересное решение. Даже не думал об этом :-)
Хранимые процедуры легитимный подход, но со своими компромиссами. Логика размазывается между приложением и БД. Для меня это усложняет отладку и понимание системы целиком.
Версионирование процедур отдельная боль. Нужно синхронизировать миграции БД с деплоем приложения.
Тестирование тоже усложняется. Для unit-тестов репозитория теперь нужна реальная БД с актуальными процедурами. Плюс vendor lock-in: PL/pgSQL !== T-SQL !== MySQL процедуры.
Странно что
Не бойся использовать разные инструменты в одном проектепри чтении статьи проходит мимо глаз. Если у вас команда DBA сильная и процедуры стандарт, отлично. Embedded SQL для тех, кто хочет держать всю логику в Go и деплоить одним бинарником.Константы в Go-файле - валидный подход. Но в чистом .sql файле работает полноценный SQL-тулинг: форматирование через pg_format, линтинг через sqlfluff, автодополнение колонок при подключении IDE к БД.
Парсер и риск ошибок. Регулярка тривиальная, 5 строк. Если разработчик забудет маркер, запрос не попадёт в map, и Get() упадёт с panic при первом же вызове. Ошибка не пройдёт незамеченной.
Ошибка компиляции. Тут я возможно действительно преувеличил. go:embed даст ошибку компиляции только если файл не найден. Однако никто кто мешает прикрутить нормальную валидацию SQL при инициализации пакета. Все это выходит на рамки простой статьи.
Как я писал в самом начали в конце статьи: это не единственный, да и не самый лучший способ организации работы с SQL файлами. Однако в большинстве случаев на моей практике он самый удобный.
Евгений спасибо, полезная статья! Было бы неплохо также детальнее разобрать мьютексы и библиотеку race (то как она работает под капатом). Думаю получился бы неплохой цикл статей по примитивам синхронизации.
Отличная статья, спасибо! Но кажется не работают якоря на содержании
В тексте ошибка.
Generics - это функции или типы, которые могут работать с любым типом данных. В Go generics были введены в версии 1.21 и они означают, что вы можете написать функцию, которая будет работать с любым типом данных, а не только с определенным.
Введены они были в 1.18
При написании пути можно использовать ~ для обозначения директории пользователя системы. По умочанию vscode складывает свои настройки в ~/.vscode. Я этого в описании не писал, сейчас напишу. Заодно лого поменяю, а то неудачное какое-то получилось )
Сделал бы раньше, но по проекту дедлайны горели.
Добавил возможность в настройках указать директорию.
Рад что понравилось ) Пиши если придумаешь что-нибудь интересное в процессе работы )
Я думаю такое можно осуществить
Кстати сделал. В версии 2.1.3 можно выделить текст в коде и на основе него создать компонент по шаблону. Более того, в названии компонента поддерживаются конструкции типа ../. Указав название шаблона как "../../modals/register user", расширение выйдет на 2 уровня вверх, создаст директорию modals и в нее положит компонент.
Прекрасная идея подтягивать сниппеты с GitHub Gist, однако он не сильно подходит для шаблонов, так как нельзя создавать директории! Но темнеменее в задачи записал :)
Тут все упирается в гибкость. Для каждого языка и фреймворка есть существует архитектура компонентов. Про реакт вообще молчу. Для этого придется создавать под каждый фреймворк отдельное расширение :)
Что касается не dumb ускорения, тут согласен. Все упирается в идеи. На момент реализации расширения, для меня нынешняя реализация была максимально удобной.
В какой-то степени статья больше нужна для сбора идей.