Что такое GORM и зачем он нужен?
GORM — это мощная и популярная ORM (Object-Relational Mapping) библиотека для языка Go. Она предоставляет разработчикам удобный способ взаимодействия с реляционными базами данных (PostgreSQL, MySQL, SQLite, SQL Server и др.), используя объектно-ориентированный подход на Go.
Зачем нужен GORM?
- Автоматизация CRUD: GORM берет на себя написание шаблонного SQL-кода для создания, чтения, обновления и удаления записей.
- Миграции схемы: Позволяет автоматически создавать и обновлять таблицы в базе данных на основе ваших Go-структур.
- Связи между таблицами: Упрощает работу с отношениями "один ко многим", "многие ко многим" и "один к одному".
- Безопасность: Встроенная защита от SQL-инъекций через параметризованные запросы.
- Производительность: Поддерживает ленивую загрузку (Lazy Loading), предзагрузку (Eager Loading) и кэширование.
- Сообщество: Огромное сообщество, множество плагинов и расширений.
Установка GORM
GORM устанавливается стандартным способом для Go-пакетов. Убедитесь, что у вас установлен Go (версии 1.18+).
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite # Для SQLite
go get -u gorm.io/driver/mysql # Для MySQL
go get -u gorm.io/driver/postgres # Для PostgreSQL
go get -u gorm.io/driver/sqlserver # Для SQL Server
Примечание: В отличие от Python (pip) или Node.js (npm), в Go нет единого менеджера пакетов. Команда go get загружает исходный код и компилирует его в ваш проект.
Быстрый старт с примером кода
Создадим простое приложение для управления пользователями с использованием SQLite.
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// User — модель данных, соответствующая таблице в БД
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:255"`
Age int
}
func main() {
// 1. Подключение к базе данных
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 2. Автомиграция — создание таблицы
db.AutoMigrate(&User{})
// 3. Создание записи (Create)
user := User{Name: "Иван Петров", Email: "ivan@example.com", Age: 30}
result := db.Create(&user)
if result.Error != nil {
fmt.Println("Ошибка создания:", result.Error)
}
fmt.Printf("Создан пользователь с ID: %d\n", user.ID)
// 4. Чтение записи (Read)
var readUser User
db.First(&readUser, user.ID) // Поиск по первичному ключу
fmt.Printf("Найден пользователь: %+v\n", readUser)
// 5. Обновление записи (Update)
db.Model(&readUser).Update("Age", 31)
fmt.Printf("Обновленный возраст: %d\n", readUser.Age)
// 6. Удаление записи (Delete)
db.Delete(&readUser)
fmt.Println("Пользователь удален")
}
Основные методы/функции GORM
1. gorm.Open(dialector, config)
Что делает: Устанавливает соединение с базой данных. Возвращает экземпляр *gorm.DB.
Параметры:
dialector— драйвер базы данных (например, sqlite.Open, mysql.Open, postgres.Open).config— конфигурация GORM (gorm.Config).
Пример:
db, err := gorm.Open(mysql.Open("user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
2. db.AutoMigrate(models ...interface{})
Что делает: Автоматически создает или обновляет таблицы в базе данных на основе переданных структур. Добавляет недостающие столбцы, индексы, ограничения.
Параметры:
models— указатели на структуры (например, &User{}, &Product{}).
Пример:
db.AutoMigrate(&User{}, &Order{})
3. db.Create(value)
Что делает: Вставляет новую запись в таблицу. Возвращает объект *gorm.DB с результатом.
Параметры:
value— указатель на структуру или срез структур.
Пример:
user := User{Name: "Анна", Email: "anna@test.com"}
result := db.Create(&user)
fmt.Println(result.RowsAffected) // 1
fmt.Println(user.ID) // ID после вставки
4. db.First(dest, conds ...interface{})
Что делает: Находит первую запись, удовлетворяющую условиям, и сохраняет её в dest. Если запись не найдена, возвращает ошибку ErrRecordNotFound.
Параметры:
dest— указатель на структуру.conds— условия поиска (ID, строка WHERE, map).
Пример:
var user User
db.First(&user, 10) // Поиск по ID = 10
db.First(&user, "email = ?", "test@example.com") // Поиск по email
5. db.Find(dest, conds ...interface{})
Что делает: Находит все записи, удовлетворяющие условиям. Результат сохраняется в срез структур.
Параметры:
dest— указатель на срез структур.conds— условия поиска.
Пример:
var users []User
db.Find(&users) // Все пользователи
db.Find(&users, "age > ?", 25) // Пользователи старше 25 лет
6. db.Model(value)
Что делает: Указывает модель, с которой будут выполняться последующие операции (Update, Where, Select и т.д.).
Параметры:
value— указатель на структуру.
Пример:
db.Model(&User{}).Where("age > ?", 18).Update("status", "active")
7. db.Where(query, args ...interface{})
Что делает: Добавляет условие WHERE к запросу. Поддерживает строки, map и структуры.
Параметры:
query— строка SQL с плейсхолдерами (?) или map/структура.args— значения для плейсхолдеров.
Пример:
var users []User
db.Where("name LIKE ?", "%Иван%").Find(&users)
db.Where(map[string]interface{}{"age": 30, "status": "active"}).Find(&users)
8. db.Order(value)
Что делает: Добавляет сортировку ORDER BY к запросу.
Параметры:
value— строка с направлением сортировки.
Пример:
db.Order("age DESC, name ASC").Find(&users)
9. db.Limit(limit) и db.Offset(offset)
Что делает: Ограничивает количество возвращаемых записей (LIMIT) и пропускает указанное количество записей (OFFSET). Используется для пагинации.
Параметры:
limit— максимальное количество записей.offset— количество пропускаемых записей.
Пример:
db.Limit(10).Offset(20).Find(&users) // Страница 3 по 10 записей
10. db.Preload(query, args ...interface{})
Что делает: Выполняет предзагрузку (Eager Loading) связанных моделей. Позволяет загрузить связанные данные одним запросом (или несколькими, но эффективно).
Параметры:
query— имя поля связи в структуре.args— дополнительные условия для связанной модели.
Пример:
type Order struct {
gorm.Model
UserID uint
User User
}
var orders []Order
db.Preload("User").Find(&orders) // Загружает заказы вместе с пользователями
11. db.Delete(value, conds ...interface{})
Что делает: Удаляет запись (мягкое удаление, если модель имеет поле DeletedAt).
Параметры:
value— указатель на структуру или условие.conds— дополнительные условия.
Пример:
db.Delete(&User{}, 10) // Удалить пользователя с ID 10
db.Where("age < ?", 18).Delete(&User{}) // Удалить всех несовершеннолетних
12. db.Raw(sql, values ...interface{})
Что делает: Выполняет произвольный SQL-запрос. Полезно для сложных запросов, которые не поддерживаются GORM напрямую.
Параметры:
sql— строка SQL-запроса.values— значения для плейсхолдеров.
Пример:
type Result struct {
Name string
Total int
}
var results []Result
db.Raw("SELECT name, COUNT(*) as total FROM users GROUP BY name").Scan(&results)
Реальный практический пример использования
Создадим REST API для интернет-магазина с использованием GORM и стандартной библиотеки net/http.
package main
import (
"encoding/json"
"log"
"net/http"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// Product — модель товара
type Product struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:200;not null" json:"name"`
Price float64 `gorm:"not null" json:"price"`
Description string `gorm:"type:text" json:"description"`
Stock int `gorm:"default:0" json:"stock"`
}
var db *gorm.DB
func main() {
var err error
db, err = gorm.Open(sqlite.Open("shop.db"), &gorm.Config{})
if err != nil {
log.Fatal("Ошибка подключения к БД:", err)
}
db.AutoMigrate(&Product{})
http.HandleFunc("/products", productsHandler)
http.HandleFunc("/products/", productHandler)
log.Println("Сервер запущен на :8080")
log.Fatal(http.ListenAndServe Также в библиотеке
OAuth клиент для TypeScript: авторизация через GitHub, Google и другие провайдеры
Работа с Excel в Go (Golang): библиотеки exelize и tealeg/xlsx
Машинное обучение на C# (.NET): обзор библиотек ML.NET, Accord.NET, TensorFlow.NET
Работа с YAML в Swift: библиотека Yams для iOS/macOS