В прикрепленном фрагменте немало вопросов, которые будут решать их один за другим:
# 1
type Post struct {
gorm.Model
Title string
Text string
Comments []Comment
}
type Comment struct {
gorm.Model
Text string
PostID uint `gorm:"foreignkey:ID;association_foreignkey:PostID"`
}
Здесь также присвоения внешнего ключа foreignkey:ID
поскольку внешний ключ ассоциации не нужен и не помещен .
Для Внешний ключ : по умолчанию gorm использует имя типа владельца плюс имя его первичного ключаполе.В вашем случае: PostID
.
Post
- это имя типа владельца ID
, равное его первичный ключ .
Вам понадобится использовать тег forignkey
, только если вы хотите изменить имя поля в структуре Comment
.Например, PostNumber
вместо PostID
.Поэтому вам нужно добавить тег с foreignkey:PostNumber
и изменить PostID в Comment
на PostNumber
.
Для Association ForeignKey , он используется, если вы хотите сказать gormиспользовать другой член, отличный от первичного ключа владельца.Например, AnotherID
в приведенном ниже примере.
Другая проблема заключается в том, что вы должны указывать эти теги в полях has many
, а не сам внешний ключ.Полный пример будет выглядеть так:
type Post struct {
gorm.Model
AnotherID uint <-------------------------------------------------------
Title string |
Text string |
Comments []Comment `gorm:"foreignkey:PostNumber;association_foreignkey:AnotherID"`
} |
|
type Comment struct { |
gorm.Model |
Text string |
PostNumber uint <----------------------
}
Обратите внимание, что эти два типа должны иметь одинаковый тип.
# 2
Можно поспорить об использовании defer db.Close()
.Из документов ,
Редко закрывать БД, так как дескриптор БД должен быть долгоживущим и совместно использоваться многими программами.
В этом примере нормально defer
закрыть базу данных.Хотя это произойдет автоматически, если вы не позвоните.Основная причина, по которой я комментирую это, состоит в том, чтобы сказать вам, что в больших приложениях вам не нужно делать это с каждым соединением.Безопасно просто вызывать sql.Open()
для глобальной переменной и использовать ее без необходимости db.Close()
.
В этом случае вы также не хотите, чтобы он открывал столько соединений, сколько пожелает, чтобы выможет потребоваться точная настройка следующих параметров:
db.DB().SetConnMaxLifetime(X) // sets the maximum amount of time a connection may be reused.
db.DB().SetMaxIdleConns(X) // sets the maximum number of connections in the idle connection pool.
db.DB().SetMaxOpenConns(X) // sets the maximum number of open connections to the database.
См. это обсуждение для получения дополнительной информации.
# 3
Приведенные ниже вызовы могут завершиться с ошибкой:
db.DropTableIfExists(&Post{}, &Comment{})
db.AutoMigrate(&Post{}, &Comment{})
db.Create(&Post{Title: "test1 title", Text: "text1"})
Итак, ВСЕГДА проверьте наличие ошибок, вы можете сделать это, проверив Error
членаgorm.DB
struct:
err = db.DropTableIfExists(&Post{}, &Comment{}).Error
if err != nil {
// handle error
}
err = db.AutoMigrate(&Post{}, &Comment{}).Error
// Check error
err = db.Create(&Post{Title: "test1 title", Text: "text1"}).Error
// Check error
# 4
Это ответ на ваш вопрос :
Вы не проходитеПередавая срез от Comment
до db.Model(&myPost).Related(&comments)
и ожидая взамен среза, который не будет работать по понятным причинам, вам нужно изменить:
var comments Comment
на
var comments []Comment