GitHub

В процессе разработки на Go нередко встаёт вопрос о создании удобного уровня абстракции для работы с базой данных: хочется иметь и простую генерацию миграций, и гибкий Query Builder. Проект Gormite был создан как раз для решения этих задач. Он предлагает облегчённый подход к ORM, при этом сохраняя гибкость при формировании SQL-запросов.

Знакомство с Gormite

Gormite – это CLI-инструмент, которая не нуждается в прямой интеграции в go.mod. Она читает конфигурацию (mapping) из YAML-файла и по указанным в нём entities генерирует миграции для базы данных. Дополнительно в Gormite входит полноценный Query Builder, позволяющий динамически формировать запросы к базе данных.

Главная идея Gormite – разделить ответствености генерации миграций и прикладного кода, чтобы разработчики могли:

  1. Легко описывать структуру таблиц через Go-структуры и теги.

  2. Генерировать SQL-миграции по этим структурам, вводя вручную SQL-код.

  3. Формировать сложные запросы в Go-коде за счёт выразительного Query Builder’а.

Установка и настройка генератора миграций

Шаг 1. Установить Gormite

go install github.com/KoNekoD/gormite/cmd/gormite@latest

Шаг 2. Создать конфигурационный файл gormite.yaml

Gormite ищет настройки по умолчанию в директории resources.

resources/gormite.yaml

gormite:  
  orm:    
    mapping:      
      Entities:
        dir: pkg/entities
  • dir – указывает, где хранятся ваши Go-сущности.

Шаг 3. Подготовить сущности

Внутри pkg/entities создавайте файлы со структурами, описывающими таблицы БД.

user.go

package entities

import "github.com/KoNekoD/gormite/test/docs_example/pkg/enums"

// User "app_user"
type User struct {	
  ID           int                `db:"id" pk:"true"`	
  Email        string             `db:"email" uniq:"email" length:"180" uniq_cond:"email:(identity_type = 'email')"`	
  Phone        string             `db:"phone" uniq:"phone" length:"10" uniq_cond:"phone:(identity_type = 'phone')"`	
  IdentityType enums.IdentityType `db:"identity_type" type:"varchar"`	
  Code         *string            `db:"code" nullable:"true"`	
  FullName     *string            `db:"full_name" default:"'Anonymous'" index:"index_full_name" index_cond:"index_full_name:(is_active = true)"`	
  IsActive     bool               `db:"is_active"`
}

type UserProfile struct {	
  ID   int   `db:"id" pk:"true"`	
  User *User `db:"user_id"`	
  Age  int   `db:"age"`
}

После того как вы подготовили сущности и YAML-файл, Gormite анализирует структуры и генерирует SQL-миграции, учитывая все настройки из тегов структур, например:

  • db – название столбца

  • pk – первичный ключ

  • nullable – допускается значение NULL

Подробнее можно ознакомиться в документации.

Query Builder

Вторая составляющая Gormite — это высокоуровневый Query Builder, призванный упростить работу с SQL. Он предоставляет полноценный функционал для построения запросов, помогающих строить запросы различной сложности.

Пример использования:

qb := gormite.NewQueryBuilder[entities.User]()

qb.Select("u.id", "u.email").
    From("app_user u").   
    Where("u.is_active = :active").   
    SetParameter("active", true).   
    OrderBy("u.id DESC").   
    SetMaxResults(10)

rows, err := qb.GetResult()
if err != nil {    
  log.Fatal(err)
}

// rows будет содержать список *entities.User, заполненных из полей "u.id" и "u.email".

Заключение

Gormite подойдёт тем, кто ищет лёгкий способ автоматизировать миграции и гибко формировать SQL — без лишних обвязок и глубокой интеграции в проект.

GitHub

Комментарии (4)


  1. paramtamtam
    11.02.2025 10:45

    Прошу не считать этот коментарий слишком токсичным (а он будет токсичным), но:

    • Каждый разработчик должен написать свой фреймворк, ровно как и то, что он должен его никому не показывать

    • Документации считаем что нет

    • Ровно как и юнит тестов

    • Контекста (context.Context) тоже нет - только по этому критерию сразу мимо кассы

    • Автоматические миграции имеют свою цену, и платить ее придется (по закону Мерфи) вот ровно тогда, когда на это совсем не будет бюджета

    • Constrains, returning, etc...

    Вы проделали классную исследовательскую работу, но собирать фидбэк таким образом - стоит ли?


  1. starwalkn
    11.02.2025 10:45

    разделить ответствености генерации миграций и прикладного кода

    И чем описание миграций на "сыром" SQL в отдельной директории будет лучше описания ямлика и добавления большого количества тегов в структуры?


    В процессе разработки на Go нередко встаёт вопрос о создании удобного уровня абстракции

    Гораздо реже чем где-либо еще. Обмазываться абстракциями ради абстракций может и принято, например, в Java, но точно не в Go.


    это CLI-инструмент, которая не нуждается в прямой интеграции в go.mod

    Но потребует дополнительной установки бинарника в контейнеры.


    SetMaxResults(10)

    А чем вам слово LIMIT не угодило? ИМХО, когда разработчик использует query builder, то он интуитивно ищет методы, схожие по названию с операциями в SQL.

    И так же я не понял, в чем смысл объединения генератора миграций и query builder.


  1. szrg
    11.02.2025 10:45

    YAML-файл

    Спасибо, нет.


  1. tuxi
    11.02.2025 10:45

    Начинать на таком одно удовольствие. Главное вовремя соскочить, чтобы развивать, тюнить и поддерживать - кто то другой был должен.