Рубрики
Технологии

sqlh — SQL в Go без boilerplate: пишем CRUD за 50 строк

> Zero-boilerplate SQL для Go. Опиши структуру тегами — и это всё.

Если вы пишете на Go и работаете с SQL-базами, вы знаете эту боль. Каждый CRUD-запрос — ручной SQL-строка, rows.Scan для каждого поля, Begin/Commit/Rollback вокруг записи, и постоянная синхронизация DDL-схемы с кодом. Шаблонный код не заканчивается никогда.

Это рассказ о sqlh — библиотеке, которая убирает всё это, оставаясь в «золотой середине» между raw SQL (слишком много работы) и тяжёлыми ORM (слишком много магии).

## §1. Проблема: Go + SQL = смерть от тысячи rows.Scan

Стандартный database/sql в Go отличен. Он даёт прочный, переносимый фундамент для любой SQL-базы. Но он намеренно оставляет тяжёлую работу за вами.

Вот как выглядит простой CRUD на чистом database/sql:

«`go

// 1. CREATE TABLE — raw DDL-строка

_, err := db.Exec(`CREATE TABLE IF NOT EXISTS user (

    id INTEGER PRIMARY KEY AUTOINCREMENT,

    name TEXT UNIQUE,

    email TEXT,

    age INTEGER

)`)

// 2. INSERT — явные placeholder и аргументы

_, err = db.Exec(

    «INSERT INTO user (name, email, age) VALUES (?, ?, ?)»,

    «Alice», «alice@example.com«, 30,

)

// 3. GET по ID — QueryRow + ручной Scan

var u User

err = db.QueryRow(«SELECT id, name, email, age FROM user WHERE id = ?», 1).

    Scan(&u.ID, &u.Name, &u.Email, &u.Age)

// 4. LIST всех — Query + rows.Next + rows.Scan в цикле

rows, err := db.Query(«SELECT id, name, email, age FROM user ORDER BY name ASC»)

var users []User

for rows.Next() {

    var u User

    if err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.Age); err != nil {

Читать далее