Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

sqlc или gorm: типобезопасный SQL или ORM в Go

sqlc компилирует SQL-файлы в типобезопасный Go-код: запросы вы пишете руками, а компилятор проверяет связку с кодом. GORM прячет SQL за цепочками на структурах: CRUD собирается мгновенно, но опечатки ловит рантайм. SQL-first против ORM-first.

Подбор под ваши приоритеты

Двигайте ползунки — насколько для вас важен каждый критерий (0 — не важен, 5 — критично). Счёт пересчитывается на лету: это взвешенное среднее оценок библиотек по критериям, а не бенчмарк.

SQL-файлы против структур с тегами

Компиляция запросов против рантайма

Минуты до рабочей связки модель-запрос

Фильтры на лету, опциональные параметры

AutoMigrate против внешних инструментов

Взвешенный счёт

  • GORMваш матч76
  • sqlc68

Под ваши веса лидирует GORM: прототипам и продуктам, где база вырастает из кода, а crud-рутина должна исчезнуть.

Пара «sqlc или gorm» — самый живой спор о доступе к данным в Go последних лет, потому что обе библиотеки популярны, а философии противоположны. sqlc — SQL-first: запросы живут в .sql-файлах, утилита анализирует их вместе со схемой и генерирует обычные Go-функции с честными типами. GORM — ORM-first: модели описываются структурами с тегами, а запросы собираются цепочками методов на живом объекте, SQL остаётся за кадром. На этой странице сравним их по одним критериям, покажем одну и ту же задачу рядом и соберём персональную рекомендацию ползунками под ваши приоритеты.

sqlc берёт предсказуемостью и типобезопасностью. Каждый запрос — именованный блок с комментарием name: GetUserByToken :one, по которому генерируется функция с типизированными параметрами и возвращаемой структурой: ошибка в имени колонки или типе ловится при генерации, а не тестом в проде. В рантайме sqlc дешевле ORM — плоские вызовы database/sql без рефлексии и хуков, а SQL остаётся честным: DBA читает запросы в файлах, планы explain пишутся без расшифровки магии. Расплата — динамика: фильтры, которые собираются на лету, даются тяжело, JOIN-граф для Preload-подобной жадной загрузки пишется руками, а миграции — отдельный инструмент.

GORM отвечает скоростью CRUD и экосистемой. Структура с тегами — уже модель: AutoMigrate создаст таблицы, Preload догрузит связи, хуки повесят логику на BeforeCreate, а soft delete включается одним полем. Цепочки db.Where(...).Order(...).Find(...) собираются в рантайме, поэтому динамические фильтры из опциональных параметров API пишутся тривиально. Сообщество крупнейшее среди Go-ORM: плагины, драйверы, рецепты. Расплата — рантайм: имена полей и операций живут в строках и рефлексии, опечатка ловится тестом, а тяжёлые запросы рано или поздно упираются в Raw и возвращают SQL-строки в проект.

Как читать итог ниже: оценки — усреднение практики команды проекта, а не лабораторные замеры; ползунки подставляют ваши приоритеты. Грубая граница: сервис с понятным набором запросов и командой, которая уважает SQL — sqlc; прототип или продукт, где база растёт из кода, а CRUD-рутина должна исчезнуть — GORM. Смешанная стратегия тоже легальна: GORM для простых моделей и миграций, sqlc для отчётов и горячих выборок. Другие развилки слоя данных разобраны в сравнениях тройки gorm-sqlc-ent, sqlc с конструктором squirrel и sqlboiler с GORM.

Одна и та же задача в каждой библиотеке

Задача-эталон для этого сравнения: посмотрите на разницу в церемониях, типах и обработке ошибок — так выбор ощущается, а не только описывается словами.

SQL-first кодогенерация: запросы в .sql-файлах, типы проверяет компилятор

package main

import (
  "context"
  "database/sql"
)

// запрос в файле query.sql:
// -- name: GetUserByToken :one
// SELECT id, name, email, token FROM users WHERE token = $1;

func main() {
  db, _ := sql.Open("pgx", "postgres://...")
  q := New(db) // сгенерировано sqlc по схеме и запросам

  // типы параметров и результата проверены при генерации
  anja, _ := q.GetUserByToken(context.Background(), tok)
  _ = anja
}

Сильные и слабые стороны

sqlc

SQL-first кодогенерация: запросы в .sql-файлах, типы проверяет компилятор

  • Честный SQL: запросы читаются, объясняются и тюнятся без расшифровки магии ORM
  • Типобезопасность: генерация ловит опечатки в колонках и типах до запуска
  • Дешёвый рантайм: плоские вызовы database/sql без рефлексии и хук-слоя
  • Динамика даётся тяжело: собираемые на лету фильтры требуют расширений или руками
  • Связи без магии: жадная загрузка Preload-стиля пишется отдельными запросами
  • Миграции вовне: схему ведут golang-migrate или goose, после правок — перегенерация

Берите, если: сервисам с понятным набором запросов, где sql остаётся честным, а типы проверяет компилятор.

GORM

ORM в рантайме: структуры с тегами, AutoMigrate и крупнейшее сообщество

  • CRUD исчезает: Preload, хуки, soft delete и транзакции из коробки
  • Динамика тривиальна: цепочки Where и Order собираются по опциональным параметрам
  • Экосистема-миллионник: плагины, драйверы и рецепты на любой случай
  • Ошибки в рантайме: опечатка в поле или цепочке ловится тестом
  • Накладные расходы: рефлексия и хук-слой заметны на горячих запросах
  • Миграции из кода: AutoMigrate удобен, но схемы в SQL-файлах не даёт

Берите, если: прототипам и продуктам, где база вырастает из кода, а crud-рутина должна исчезнуть.

Оценки по критериям

Шкала 1-5: экспертная оценка команды проекта по практике, а не синтетика.

Сравнение sqlc, GORM по критериям
КритерийsqlcGORM
Источник правдыSQL-файлы против структур с тегами
ТипобезопасностьКомпиляция запросов против рантайма
Скорость CRUDМинуты до рабочей связки модель-запрос
Динамические запросыФильтры на лету, опциональные параметры
МиграцииAutoMigrate против внешних инструментов

Вердикт: когда что выбирать

sqlc и GORM решают одну задачу с противоположных концов: sqlc делает SQL первоклассным артефактом и проверяет его компиляцией, GORM делает SQL необязательным и собирает его в рантайме из структур. Выбирайте по тому, кто в проекте хозяин запросов — разработчик, который любит SQL, или фреймворк, который его прячет. Гибрид «GORM для CRUD, sqlc для отчётов» — рабочая практика больших сервисов.

Запросы известны заранее: API-эндпоинты, отчёты, витриныsqlcТипобезопасность и честный SQL с планами explain без расшифровки
Прототип или MVP: база растёт вместе с кодомGORMAutoMigrate и связи из коробки — модель уже таблица
Динамические фильтры из опциональных параметров APIGORMЦепочки Where собираются в рантайме без SQL-конструкторов
Большой сервис с горячими выборками и отчётамиGORM + sqlcCRUD на ORM, отчёты на sqlc — оба мира без компромиссов

А что выбрали вы?

Кликните по своему выбору — голос сохранится только в вашем браузере (персональные данные никуда не отправляются).

Частые вопросы

Что выбрать — sqlc или GORM?

Считайте через хозяина запросов. Если команда понимает SQL, а набор запросов стабилен — sqlc даст типобезопасность до запуска и честные планы explain. Если проект растёт от структуры к структуре, а рутину CRUD хочется спрятать — GORM закроет её из коробки с AutoMigrate и Preload. Практика больших сервисов — гибрид: GORM для жизненного цикла моделей, sqlc для тяжёлых и отчётных запросов.

Как в sqlc жить с динамическими фильтрами?

Три пути. Первый — покрывать варианты отдельными запросами: WHERE без условий, WHERE с фильтром, WHERE с диапазоном — sqlc генерирует функцию на каждый. Второй — расширения по флагам в конфиге sqlc (emit_enum, overrides) и конструкции вроде COALESCE с NULL-параметрами. Третий — выносить по-настоящему динамические выборки в sql builder вроде squirrel: у нас есть отдельное сравнение sqlc со squirrel, где этот гибрид разобран.

Заменяет ли sqlc AutoMigrate?

Нет, и это принципиально: sqlc читает схему и запросы, но не создаёт и не меняет таблицы. Миграции остаются за внешним инструментом — golang-migrate, goose или Atlas. Такой раздел нравится командам с сильным DBA: миграции ревьюятся как SQL-артефакты, а sqlc после изменения схемы просто перегенерирует код. GORM с AutoMigrate живёт по-другому — схема выводится из структур приложения.

Мы уже на GORM — стоит ли добавлять sqlc?

Да, если появились тяжёлые выборки: отчёты, агрегаты, выгрузки, где GORM-цепочки превращаются в Raw или тянут рефлексию на больших таблицах. sqlc встраивается рядом без переписывания моделей: те же таблицы, отдельные .sql-файлы, сгенерированные функции вызываются рядом с GORM-кодом. Начните с одного горячего отчёта — это самый дешёвый способ почувствовать разницу в предсказуемости.

Другие сравнения