Работа с базами данных в Go: PostgreSQL и MongoDB для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с базами данных в Go: PostgreSQL и MongoDB для начинающих

Go (Golang) — современный компилируемый язык, который завоевал популярность благодаря высокой производительности, простоте и встроенной поддержке конкурентности. При разработке веб-сервисов и приложений практически всегда возникает необходимость взаимодействия с базами данных. В этой статье мы рассмотрим, как работать с двумя популярными СУБД: реляционной PostgreSQL и документо-ориентированной MongoDB. Материал ориентирован на начинающих разработчиков, которые уже знакомы с основами Go.

1. Подготовка окружения и установка драйверов

Прежде чем начать, убедитесь, что у вас установлен Go (версия 1.16+) и запущены соответствующие СУБД. Для работы с PostgreSQL потребуется драйвер lib/pq, а для MongoDB — официальный драйвер mongo-go-driver.

go get github.com/lib/pq
go get go.mongodb.org/mongo-driver/mongo

Создайте новый модуль:

go mod init example.com/db-demo

2. Работа с PostgreSQL в Go

PostgreSQL — мощная реляционная база данных с поддержкой SQL. В Go мы используем стандартный пакет database/sql вместе с драйвером lib/pq.

2.1 Подключение к базе данных

Для подключения необходимо указать строку соединения (DSN) в формате: host=... port=... user=... password=... dbname=... sslmode=disable.

package main

import (
    "database/sql"
    "fmt"
    "log"
    _ "github.com/lib/pq"
)

func main() {
    connStr := "host=localhost port=5432 user=postgres password=secret dbname=testdb sslmode=disable"
    db, err := sql.Open("postgres", connStr)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        log.Fatal("Не удалось подключиться:", err)
    }
    fmt.Println("Подключение к PostgreSQL установлено!")
}

2.2 Создание таблицы и CRUD-операции

Рассмотрим создание таблицы users и выполнение базовых операций.

// Создание таблицы
createTable := `
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    age INT
);`

_, err = db.Exec(createTable)
if err != nil {
    log.Fatal(err)
}

// Вставка данных
sqlInsert := `INSERT INTO users (name, email, age) VALUES ($1, $2, $3) RETURNING id`
var userID int
err = db.QueryRow(sqlInsert, "Иван Петров", "ivan@example.com", 30).Scan(&userID)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Добавлен пользователь с ID: %d\n", userID)

// Запрос данных
rows, err := db.Query("SELECT id, name, email, age FROM users")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
    var u struct {
        ID    int
        Name  string
        Email string
        Age   int
    }
    err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.Age)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("ID: %d, Имя: %s, Email: %s, Возраст: %d\n", u.ID, u.Name, u.Email, u.Age)
}

2.3 Использование подготовленных запросов

Подготовленные запросы (prepared statements) повышают безопасность и производительность, особенно при повторяющихся операциях.

stmt, err := db.Prepare("UPDATE users SET age = $1 WHERE id = $2")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

_, err = stmt.Exec(35, 1)
if err != nil {
    log.Fatal(err)
}
fmt.Println("Возраст пользователя обновлён")

3. Работа с MongoDB в Go

MongoDB — документо-ориентированная база данных NoSQL. В Go работа с ней осуществляется через официальный драйвер mongo-go-driver, который использует контексты для управления временем выполнения операций.

3.1 Подключение к MongoDB

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    client, err := mongo.Connect(context.TODO(), clientOptions)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect(context.TODO())

    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    err = client.Ping(ctx, nil)
    if err != nil {
        log.Fatal("Не удалось подключиться:", err)
    }
    fmt.Println("Подключение к MongoDB установлено!")
}

3.2 CRUD-операции с коллекциями

В MongoDB данные хранятся в коллекциях, которые содержат документы (структуры, похожие на JSON).

collection := client.Database("testdb").Collection("users")

// Вставка одного документа
type User struct {
    Name  string `bson:"name"`
    Email string `bson:"email"`
    Age   int    `bson:"age"`
}

user := User{Name: "Мария Смирнова", Email: "maria@example.com", Age: 28}
insertResult, err := collection.InsertOne(context.TODO(), user)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Добавлен документ с ID: %v\n", insertResult.InsertedID)

// Поиск всех документов
cur, err := collection.Find(context.TODO(), bson.D{})
if err != nil {
    log.Fatal(err)
}
defer cur.Close(context.TODO())

for cur.Next(context.TODO()) {
    var result User
    err := cur.Decode(&result)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Имя: %s, Email: %s, Возраст: %d\n", result.Name, result.Email, result.Age)
}

// Обновление документа
filter := bson.D{{"name", "Мария Смирнова"}}
update := bson.D{{"$set", bson.D{{"age", 29}}}}
_, err = collection.UpdateOne(context.TODO(), filter, update)
if err != nil {
    log.Fatal(err)
}

// Удаление документа
_, err = collection.DeleteOne(context.TODO(), filter)
if err != nil {
    log.Fatal(err)
}

3.3 Индексы и агрегация

MongoDB поддерживает создание индексов для ускорения запросов:

indexModel := mongo.IndexModel{
    Keys: bson.D{{"email", 1}}, //                

Блоги

Рекомендаций по книгам