0Pricing
Go Academy · Урок

Ассоциации

Моделируйте связи

«Ассоциации» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Моделирование связей

Связи GORM сопоставляют отношения между таблицами с полями структур. Выделяют четыре вида: один к одному, один ко многим, принадлежность и многие ко многим.

  • Представляйте внешние ключи как поля структур
  • Автоматически загружайте связанные данные
  • Создавайте связанные записи одновременно

Связь «один ко многим»

У пользователя может быть много публикаций. Родительский объект содержит срез дочерних объектов, а дочерний объект — внешний ключ, ссылающийся на родительский.

type User struct {
    gorm.Model
    Name  string
    Posts []Post
}

type Post struct {
    gorm.Model
    Title  string
    UserID uint
}

Принадлежность к родительскому объекту

С точки зрения дочернего объекта публикация принадлежит пользователю. Добавьте поле User и внешний ключ UserID, чтобы выразить эту связь.

type Post struct {
    gorm.Model
    Title  string
    UserID uint
    User   User
}

Связь «один к одному»

Связь «один к одному» похожа на связь «один ко многим», но предполагает одну связанную запись, например один профиль пользователя. Дочерний объект содержит внешний ключ.

type User struct {
    gorm.Model
    Profile Profile
}

type Profile struct {
    gorm.Model
    UserID uint
    Bio    string
}

Связь «многие ко многим»

Пользователи и роли связаны отношением «многие ко многим» через промежуточную таблицу. Тег many2many задаёт имя этой таблицы, записываемое как gorm:"many2many:user_roles;" в обратных кавычках после поля Roles.

type User struct {
    gorm.Model
    // Roles field tag: gorm:"many2many:user_roles;"
    Roles []Role
}

type Role struct {
    gorm.Model
    Name string
}

Preload

По умолчанию связанные данные не загружаются. Preload указывает GORM получить связи отдельным запросом, избавляя Вас от ручного отдельного поиска.

var user User
db.Preload("Posts").First(&user, 1)
fmt.Println(len(user.Posts))

Вложенный Preload

Вы можете выполнить Preload для нескольких уровней с помощью пути с точками, загрузив публикации пользователя и комментарии каждой публикации одной цепочкой вызовов.

db.Preload("Posts.Comments").First(&user, 1)

Рабочая симуляция связей

GORM нужна база данных, поэтому этот запускаемый пример моделирует связь «один ко многим» и предварительную загрузку с помощью срезов в памяти.

package main

import "fmt"

type Post struct {
    ID     int
    UserID int
    Title  string
}

type User struct {
    ID    int
    Name  string
    Posts []Post
}

func preload(u *User, all []Post) {
    for _, p := range all {
        if p.UserID == u.ID {
            u.Posts = append(u.Posts, p)
        }
    }
}

func main() {
    u := User{ID: 1, Name: "Ada"}
    all := []Post{{1, 1, "Hello"}, {2, 1, "World"}, {3, 2, "Other"}}
    preload(&u, all)
    fmt.Printf("%s has %d posts\n", u.Name, len(u.Posts))
}

Создание вместе со связями

Если передать срез в поле до вызова Create, GORM вставит родительский объект и его дочерние объекты вместе, а внешние ключи будут связаны автоматически.

user := User{Name: "Ada", Posts: []Post{{Title: "Hi"}}}
db.Create(&user)

Проблема N+1

Если перебирать родительские объекты и запрашивать дочерние при каждой итерации, получится один запрос на каждый родительский объект — проблема N+1. Preload решает её, объединяя загрузку связанных данных в один дополнительный запрос.

Режим связей

API Association добавляет, заменяет, удаляет или очищает связанные записи без ручной работы с внешними ключами, например db.Model(&user).Association("Posts").Append(&post).

Быстрая проверка

Проверьте свои знания о связях.

Итоги

Вы изучили связи:

  • отношения моделей «один к одному», «один ко многим», принадлежность и «многие ко многим»
  • внешние ключи являются полями структур, например UserID
  • Preload загружает связи и предотвращает проблему N+1
  • при создании родительского объекта вместе с дочерними внешние ключи связываются автоматически
  • режим связей добавляет, заменяет или очищает отношения

Часто задаваемые вопросы

Урок «Ассоциации» бесплатный?

Да — полный текст урока «Ассоциации» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Ассоциации»?

Моделируйте связи Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Ассоциации»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Модели и AutoMigrate
  2. Операции CRUD
  3. Ассоциации
  4. Хуки и области видимости
← Назад к Go Academy