Введение: Почему Go и базы данных — идеальная пара
Go (Golang) — это компилируемый, статически типизированный язык, созданный для высокой производительности и простоты разработки. Одним из ключевых преимуществ Go является его богатая стандартная библиотека и экосистема драйверов для работы с базами данных. В этой статье мы разберем, как подключаться и выполнять операции с двумя самыми популярными системами управления базами данных (СУБД): реляционной PostgreSQL и документоориентированной MongoDB.
Мы рассмотрим установку драйверов, написание CRUD-операций (Create, Read, Update, Delete) и лучшие практики для каждого типа БД в контексте Go-приложений.
1. Работа с PostgreSQL в Go
PostgreSQL — мощная объектно-реляционная СУБД с открытым исходным кодом. Для работы с ней в Go существует несколько драйверов, но наиболее популярными являются lib/pq и pgx. pgx — более современный и производительный, поэтому мы будем использовать его.
1.1. Установка драйвера
Установите пакет pgx через go get:
go get github.com/jackc/pgx/v5
1.2. Подключение к базе данных
Создадим файл main.go и установим соединение с PostgreSQL. Обратите внимание на использование контекста (context.Background()) — это стандартный паттерн в Go для управления временем жизни запросов.
package main
import (
"context"
"fmt"
"log"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
// Строка подключения: postgres://username:password@host:port/dbname
connString := "postgres://user:password@localhost:5432/mydb"
// Создаем пул соединений (рекомендуется для production)
pool, err := pgxpool.New(context.Background(), connString)
if err != nil {
log.Fatal("Не удалось создать пул соединений:", err)
}
defer pool.Close()
// Проверяем соединение
err = pool.Ping(context.Background())
if err != nil {
log.Fatal("Не удалось подключиться к БД:", err)
}
fmt.Println("Успешно подключено к PostgreSQL!")
}
1.3. Выполнение SQL-запросов (CRUD)
Рассмотрим основные операции на примере таблицы users.
Создание таблицы (CREATE)
// Выполнение DDL-запроса
_, err = pool.Exec(context.Background(), `
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT
)
`)
if err != nil {
log.Fatal("Ошибка создания таблицы:", err)
}
Вставка данных (INSERT)
// Вставка с возвратом ID
var userID int
err = pool.QueryRow(context.Background(),
"INSERT INTO users (name, email, age) VALUES ($1, $2, $3) RETURNING id",
"Алексей", "alex@example.com", 30).Scan(&userID)
if err != nil {
log.Fatal("Ошибка вставки:", err)
}
fmt.Printf("Добавлен пользователь с ID: %d\n", userID)
Чтение данных (SELECT)
// Получение одного пользователя
type User struct {
ID int
Name string
Email string
Age int
}
var user User
err = pool.QueryRow(context.Background(),
"SELECT id, name, email, age FROM users WHERE id = $1", 1).
Scan(&user.ID, &user.Name, &user.Email, &user.Age)
if err != nil {
log.Fatal("Пользователь не найден:", err)
}
fmt.Printf("Найден: %+v\n", user)
Обновление и удаление (UPDATE/DELETE)
// Обновление
_, err = pool.Exec(context.Background(),
"UPDATE users SET age = $1 WHERE id = $2", 31, 1)
// Удаление
_, err = pool.Exec(context.Background(),
"DELETE FROM users WHERE id = $1", 1)
2. Работа с MongoDB в Go
MongoDB — ведущая NoSQL-база данных, хранящая данные в формате BSON (бинарный JSON). Официальный драйвер от MongoDB называется mongo-go-driver.
2.1. Установка драйвера
go get go.mongodb.org/mongo-driver/mongo
2.2. Подключение к MongoDB
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongodb-driver/mongo/options"
)
func main() {
// Строка подключения
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
// Создаем клиент
client, err := mongo.NewClient(clientOptions)
if err != nil {
log.Fatal(err)
}
// Устанавливаем соединение (с таймаутом)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
// Проверка
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal("Не удалось подключиться к MongoDB:", err)
}
fmt.Println("Успешно подключено к MongoDB!")
// Получаем доступ к базе данных и коллекции
db := client.Database("mydb")
collection := db.Collection("users")
_ = collection // используем далее
}
2.3. CRUD-операции с MongoDB
MongoDB использует структуры Go, аннотированные тегами BSON, для маппинга данных.
Определение модели и вставка (INSERT)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"`
Email string `bson:"email"`
Age int `bson:"age"`
}
// Вставка одного документа
newUser := User{
Name: "Мария",
Email: "maria@example.com",
Age: 25,
}
result, err := collection.InsertOne(ctx, newUser)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Вставлен документ с ID: %v\n", result.InsertedID)
Чтение документов (FIND)
// Поиск одного