守着星空守着你
我根据你的描述写了一个示例代码,你可以在底部找到完整的代码。让我们来看看不同的选择:// Use auto_preload and .Firstdb.Set("gorm:auto_preload", true).Where("name = ?", "m0").First(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[]}]}]因此,.First您可以得到部分,但不能得到Sections.Fields// Use auto_preload and .Finddb.Set("gorm:auto_preload", true).Find(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[]}]} {ID:2 Name:m1 Status:0 Sections:[{ID:1 Name:s0 Fields:[]}]}]与.Find您获得相同的行为.First// Use .Preloaddb.Preload("Sections").Preload("Sections.Fields").Find(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[{ID:1 Name:f0} {ID:2 Name:f1}]}]} {ID:2 Name:m1 Status:0 Sections:[{ID:1 Name:s0 Fields:[{ID:1 Name:f0} {ID:3 Name:f2}]}]}]通过显式预加载,您可以同时加载Sections和Sections.Fields。仅使用auto_preload预加载直接字段,而不是更深的字段。IMO 使用显式预加载通常是一种更好的做法。完整代码:package mainimport ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" "log")type Module struct { ID int `gorm:"primary_key"` Name string Status int Sections []Section `gorm:"many2many:module_sections;"`}type Section struct { ID int `gorm:"primary_key"` Name string Fields []Field `gorm:"many2many:section_fields;"`}type Field struct { ID int `gorm:"primary_key"` Name string}func preloadingSample() error { db, err := gorm.Open("sqlite3", "test.db") if err != nil { return fmt.Errorf("open DB failed: %w", err) } defer db.Close() err = db.AutoMigrate( &Module{}, &Section{}, &Field{}, ).Error if err != nil { return fmt.Errorf("migration failed: %w", err) } // Delete everything in DB db.Delete(&Module{}) db.Delete(&Section{}) db.Delete(&Field{}) // Put some sample data in DB sampleFields := []Field{ {Name: "f0"}, {Name: "f1"}, {Name: "f2"}, {Name: "f3"}, } for idx := range sampleFields { err = db.Create(&sampleFields[idx]).Error if err != nil { return fmt.Errorf("failed to create: %w", err) } } sampleSections := []Section{ {Name: "s0", Fields: []Field{sampleFields[0], sampleFields[2]}}, {Name: "s1", Fields: []Field{sampleFields[0], sampleFields[1]}}, } for idx := range sampleSections { err = db.Create(&sampleSections[idx]).Error if err != nil { return fmt.Errorf("failed to create: %w", err) } } sampleModules := []Module{ {Name: "m0", Sections: []Section{sampleSections[1]}}, {Name: "m1", Sections: []Section{sampleSections[0]}}, } for idx := range sampleModules { err = db.Create(&sampleModules[idx]).Error if err != nil { return fmt.Errorf("failed to create: %w", err) } } var modules []Module // Load just one module with auto_preload err = db.Set("gorm:auto_preload", true).Where("name = ?", "m0").First(&modules).Error if err != nil { return fmt.Errorf("auto_preload first: %w", err) } fmt.Printf("%+v\n", modules) // Load all modules with auto_preload err = db.Set("gorm:auto_preload", true).Find(&modules).Error if err != nil { return fmt.Errorf("auto_preload find: %w", err) } fmt.Printf("%+v\n", modules) // Explicitly load err = db.Preload("Sections").Preload("Sections.Fields").Find(&modules).Error if err != nil { return fmt.Errorf("preload find: %w", err) } fmt.Printf("%+v\n", modules) return nil}func main() { err := preloadingSample() if err != nil { log.Fatal(err) }}