9. Работа с базами данных #
Работа с базами данных в Go включает взаимодействие через стандартный пакет database/sql
и использование ORM для упрощения операций. Go также поддерживает интеграцию с NoSQL-решениями.
9.1 Введение в database/sql
#
Пакет database/sql
предоставляет интерфейс для работы с реляционными базами данных (MySQL, PostgreSQL, SQLite и др.). Для подключения к базе данных используются драйверы, такие как github.com/lib/pq
для PostgreSQL или github.com/go-sql-driver/mysql
для MySQL.
Пример подключения к базе данных и выполнения запросов:
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq" // Драйвер PostgreSQL
)
func main() {
connStr := "user=postgres password=secret dbname=mydb sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
panic(err)
}
defer db.Close()
// Выполнение запроса
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
err := rows.Scan(&id, &name)
if err != nil {
panic(err)
}
fmt.Printf("ID: %d, Name: %s\n", id, name)
}
}
9.2 Использование ORM (GORM, Ent) #
GORM #
GORM (gorm.io/gorm
) — это популярный ORM для Go, предоставляющий высокоуровневый интерфейс для работы с базой данных.
Пример работы с GORM:
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type User struct {
ID uint
Name string
Age int
}
func main() {
dsn := "user=postgres password=secret dbname=mydb sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
// Миграция схемы
db.AutoMigrate(&User{})
// Создание записи
db.Create(&User{Name: "Иван", Age: 30})
// Чтение записи
var user User
db.First(&user, 1) // Найти пользователя с ID=1
fmt.Println(user)
// Обновление записи
db.Model(&user).Update("Age", 31)
// Удаление записи
db.Delete(&user)
}
Ent #
Ent (entgo.io/ent
) — ORM с генерацией кода.
Пример работы с Ent:
- Установите Ent и создайте схему:
go install entgo.io/ent/cmd/ent ent init User
- Определите схему:
package schema import "entgo.io/ent/schema/field" type User struct { ent.Schema } func (User) Fields() []ent.Field { return []ent.Field{ field.String("name"), field.Int("age"), } }
- Используйте сгенерированный код:
client, err := ent.Open("postgres", "user=postgres password=secret dbname=mydb sslmode=disable") defer client.Close() user := client.User.Create().SetName("Иван").SetAge(30).Save(context.Background()) fmt.Println(user)
9.3 Транзакции и обработка ошибок #
Используйте транзакции для обеспечения атомарности операций.
Пример с database/sql
:
tx, err := db.Begin()
if err != nil {
panic(err)
}
_, err = tx.Exec("INSERT INTO accounts (id, balance) VALUES ($1, $2)", 1, 100)
if err != nil {
tx.Rollback()
panic(err)
}
_, err = tx.Exec("UPDATE accounts SET balance = balance - 50 WHERE id = $1", 1)
if err != nil {
tx.Rollback()
panic(err)
}
err = tx.Commit()
if err != nil {
panic(err)
}
9.4 Миграции и схема базы данных #
Миграции позволяют управлять изменениями структуры базы данных.
Инструмент GORM: #
go install github.com/go-gormigrate/gormigrate/v2
Пример миграции:
package main
import (
"gorm.io/gorm"
"github.com/go-gormigrate/gormigrate/v2"
)
func main() {
db, _ := gorm.Open(postgres.Open(dsn), &gorm.Config{})
m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
{
ID: "20231208_create_users",
Migrate: func(tx *gorm.DB) error {
type User struct {
ID uint
Name string
}
return tx.AutoMigrate(&User{})
},
Rollback: func(tx *gorm.DB) error {
return tx.Migrator().DropTable("users")
},
},
})
if err := m.Migrate(); err != nil {
panic(err)
}
fmt.Println("Миграция выполнена")
}
9.5 Интеграция с NoSQL #
MongoDB #
Для работы с MongoDB используйте драйвер go.mongodb.org/mongo-driver
.
Пример подключения и запроса:
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
panic(err)
}
collection := client.Database("testdb").Collection("users")
// Добавление документа
res, err := collection.InsertOne(ctx, bson.M{"name": "Иван", "age": 30})
fmt.Println("ID добавленного документа:", res.InsertedID)
// Чтение документа
var user bson.M
err = collection.FindOne(ctx, bson.M{"name": "Иван"}).Decode(&user)
fmt.Println("Найденный пользователь:", user)
}
Redis #
Для работы с Redis используйте пакет github.com/redis/go-redis/v9
.
Пример:
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
// Установка ключа
rdb.Set(ctx, "name", "Иван", 0)
// Чтение ключа
name, _ := rdb.Get(ctx, "name").Result()
fmt.Println("Имя:", name)
}
Эти инструменты позволяют эффективно работать как с реляционными, так и с NoSQL базами данных, покрывая широкий спектр задач.