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

Wait 5 sec.

> 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 + ручной Scanvar u Usererr = 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 []Userfor rows.Next() {    var u User    if err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.Age); err != nil { Читать далее