英文:
Unable to run Go server due to "panic: reflect.StructOf: duplicate field"
问题
我正在尝试创建一个包含3个主要模型和3个控制器的后端API,但是每当我运行go run main.go
时遇到问题,因为它给我返回了一个错误消息,指出我有一个重复的DeveloperID
字段:
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
panic: reflect.StructOf: duplicate field DeveloperID
goroutine 1 [running]:
reflect.StructOf({0xc0003ee000, 0x3, 0xc00039e980})
/snap/go/8627/src/reflect/type.go:2597 +0x1d45
gorm.io/gorm/schema.(*Schema).buildMany2ManyRelation(0xc00000c3c0, 0xc0001fcab0, 0xc0003cb6c0, {0x9a9922, 0xc0003b7470})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/relationship.go:270 +0xc25
gorm.io/gorm/schema.(*Schema).parseRelation(0xc00000c3c0, 0xc0003cb6c0)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/relationship.go:79 +0x31f
gorm.io/gorm/schema.ParseWithSpecialTableName({0x9ab3c0, 0xc0000de580}, 0xc0003b74d0, {0xb35250, 0xc0003b7470}, {0x0, 0x0})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/schema.go:275 +0x2105
gorm.io/gorm.(*Statement).ParseWithSpecialTableName(0xc0003ca540, {0x9ab3c0, 0xc0000de580}, {0x0, 0x203000})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/statement.go:463 +0x67
gorm.io/gorm.(*Statement).Parse(...)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/statement.go:459
gorm.io/gorm/migrator.Migrator.ReorderModels.func1({0x9ab3c0, 0xc0000de580}, 0x1)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:702 +0x179
gorm.io/gorm/migrator.Migrator.ReorderModels({{0x60, 0xc0003b77a0, {0xb37360, 0xc0003b77d0}}}, {0xc0003d8460, 0x1, 0xa51940}, 0x1)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:765 +0x630
gorm.io/gorm/migrator.Migrator.AutoMigrate({{0x0, 0xc0003b77a0, {0xb37360, 0xc0003b77d0}}}, {0xc0003d8460, 0x0, 0x0})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:90 +0x6d
gorm.io/gorm.(*DB).AutoMigrate(0xb371a8, {0xc0003d8460, 0x1, 0x1})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator.go:26 +0x43
SMS-Go/models.ConnectDatabase()
/home/nero/go/src/SMS-Go/models/setup.go:17 +0x111
main.main()
/home/nero/go/src/SMS-Go/main.go:13 +0x27
exit status 2
这是我的模型和正在被读取的控制器:
trigger_controller.go
:
/controllers/trigger_controller.go
package controllers
import (
"SMS-Go/models"
"net/http"
"time"
"github.com/gin-gonic/gin"
uuid "github.com/nu7hatch/gouuid"
)
type MessageInput struct {
TeamID int `json:"team_id" binding:"required"`
Title string `json:"title" binding:"required"`
Content string `json:"content" binding:"required"`
}
// type Response struct {
// TeamID string `json:"team_id"`
// Sms Sms `json:"sms"`
// Email Email `json:"email"`
// }
// type Sms struct {
// ID string `json:"id"`
// Mobiles []string `json:"mobiles"`
// Content string `json:"content"`
// SentAt string `json:"sent_at"`
// }
// type Email struct {
// ID string `json:"id"`
// Emails []string `json:"emails"`
// Title string `json:"title"`
// Content string `json:"content"`
// SentAt string `json:"sent_at"`
// }
func Notification(c *gin.Context) {
var input MessageInput //input validation
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
u1, err := uuid.NewV4()
_ = err
message := models.Message{TeamID: input.TeamID, Title: input.Title, Content: input.Content}
models.DB.Create(&message)
mob := models.DB.Raw(`SELECT "developers"."mobile" FROM "developers" INNER JOIN "developer_teams" ON "developers"."id" = "developer_teams"."developer_id" WHERE "developer_teams"."team_id"`)
mail := models.DB.Raw(`SELECT "developers"."email" FROM "developers" INNER JOIN "developer_teams" ON "developers"."id" = "developer_teams"."developer_id" WHERE "developer_teams"."team_id"`)
c.JSON(http.StatusOK, gin.H{
"team_id": input.TeamID,
"sms": gin.H{
"id": u1,
"mobiles": mob,
"content": input.Content,
"sent_at": time.Now(),
},
"email": gin.H{
"id": u1,
"emails": mail,
"title": input.Title,
"content": input.Content,
"sent_at": time.Now(),
},
},
)
}
team.go
:
/models/team.go
package models
import "gorm.io/gorm"
type Team struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Dept string `json:"dept_name"`
Messages []Message
}
developer.go
:
/models/developer.go
package models
import "gorm.io/gorm"
type Developer struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Full_name string `json:"full_name"`
Email string `json:"email"`
Mobile string `json:"mobile"`
Developers []Developer `gorm:"many2many:developer_teams"`
}
message.go
:
/models/message.go
package models
import "gorm.io/gorm"
type Message struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
TeamID int `json:"team_id"`
Title string `json:"title"`
Content string `json:"content"`
Team Team
}
我试图使得当您在trigger_notification
中以JSON格式输入字段时,它会返回一个JSON响应,显示属于特定团队的所有开发人员,通过mobile和email对象。
响应应该类似于这样:
{
"team_id": "team_id",
"sms": {
"id": "ARANDOMID",
"mobiles": ["numer1","number2"],
"content": "the content of this message",
"sent_at": "18:54:34 IST 2021"
},
"email": {
"id": "ARANDOMID",
"emails": ["email1@email.com", "email2@email.com"],
"title": "Used in emails for title",
"content": "the content of this message",
"sent_at": "18:54:34 IST 2021"
}
}
setup.go
:
package models
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectDatabase() {
database, err := gorm.Open(sqlite.Open("sms-go.db"), &gorm.Config{})
if err != nil {
panic("Failure to connect to database")
}
database.AutoMigrate(&Developer{})
database.AutoMigrate(&Message{})
database.AutoMigrate(&Team{})
DB = database
}
英文:
I'm trying to create a backend API that contains 3 main models and 3 controllers but I'm running into trouble whenever I run go run main.go
because it gives me this error message stating that I have a duplicate DeveloperID
field:
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
panic: reflect.StructOf: duplicate field DeveloperID
goroutine 1 [running]:
reflect.StructOf({0xc0003ee000, 0x3, 0xc00039e980})
/snap/go/8627/src/reflect/type.go:2597 +0x1d45
gorm.io/gorm/schema.(*Schema).buildMany2ManyRelation(0xc00000c3c0, 0xc0001fcab0, 0xc0003cb6c0, {0x9a9922, 0xc0003b7470})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/relationship.go:270 +0xc25
gorm.io/gorm/schema.(*Schema).parseRelation(0xc00000c3c0, 0xc0003cb6c0)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/relationship.go:79 +0x31f
gorm.io/gorm/schema.ParseWithSpecialTableName({0x9ab3c0, 0xc0000de580}, 0xc0003b74d0, {0xb35250, 0xc0003b7470}, {0x0, 0x0})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/schema/schema.go:275 +0x2105
gorm.io/gorm.(*Statement).ParseWithSpecialTableName(0xc0003ca540, {0x9ab3c0, 0xc0000de580}, {0x0, 0x203000})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/statement.go:463 +0x67
gorm.io/gorm.(*Statement).Parse(...)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/statement.go:459
gorm.io/gorm/migrator.Migrator.ReorderModels.func1({0x9ab3c0, 0xc0000de580}, 0x1)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:702 +0x179
gorm.io/gorm/migrator.Migrator.ReorderModels({{0x60, 0xc0003b77a0, {0xb37360, 0xc0003b77d0}}}, {0xc0003d8460, 0x1, 0xa51940}, 0x1)
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:765 +0x630
gorm.io/gorm/migrator.Migrator.AutoMigrate({{0x0, 0xc0003b77a0, {0xb37360, 0xc0003b77d0}}}, {0xc0003d8460, 0x0, 0x0})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator/migrator.go:90 +0x6d
gorm.io/gorm.(*DB).AutoMigrate(0xb371a8, {0xc0003d8460, 0x1, 0x1})
/home/nero/go/pkg/mod/gorm.io/gorm@v1.22.3/migrator.go:26 +0x43
SMS-Go/models.ConnectDatabase()
/home/nero/go/src/SMS-Go/models/setup.go:17 +0x111
main.main()
/home/nero/go/src/SMS-Go/main.go:13 +0x27
exit status 2
Here are my models and the controller that is being read:
trigger_controller.go
:
/controllers/trigger_controller.go
package controllers
import (
"SMS-Go/models"
"net/http"
"time"
"github.com/gin-gonic/gin"
uuid "github.com/nu7hatch/gouuid"
)
type MessageInput struct {
TeamID int `json:"team_id" binding:"required"`
Title string `json:"title" binding:"required"`
Content string `json:"content" binding:"required"`
}
// type Response struct {
// TeamID string `json:"team_id"`
// Sms Sms `json:"sms"`
// Email Email `json:"email"`
// }
// type Sms struct {
// ID string `json:"id"`
// Mobiles []string `json:"mobiles"`
// Content string `json:"content"`
// SentAt string `json:"sent_at"`
// }
// type Email struct {
// ID string `json:"id"`
// Emails []string `json:"emails"`
// Title string `json:"title"`
// Content string `json:"content"`
// SentAt string `json:"sent_at"`
// }
func Notification(c *gin.Context) {
var input MessageInput //input validation
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
u1, err := uuid.NewV4()
_ = err
message := models.Message{TeamID: input.TeamID, Title: input.Title, Content: input.Content}
models.DB.Create(&message)
mob := models.DB.Raw(`SELECT "developers"."mobile" FROM "developers" INNER JOIN "developer_teams" ON "developers"."id" = "developer_teams"."developer_id" WHERE "developer_teams"."team_id"`)
mail := models.DB.Raw(`SELECT "developers"."email" FROM "developers" INNER JOIN "developer_teams" ON "developers"."id" = "developer_teams"."developer_id" WHERE "developer_teams"."team_id"`)
c.JSON(http.StatusOK, gin.H{
"team_id": input.TeamID,
"sms": gin.H{
"id": u1,
"mobiles": mob,
"content": input.Content,
"sent_at": time.Now(),
},
"email": gin.H{
"id": u1,
"emails": mail,
"title": input.Title,
"content": input.Content,
"sent_at": time.Now(),
},
},
)
}
team.go
:
/models/team.go
package models
import "gorm.io/gorm"
type Team struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Dept string `json:"dept_name"`
Messages []Message
}
developer.go
:
/models/developer.go
package models
import "gorm.io/gorm"
type Developer struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Full_name string `json:"full_name"`
Email string `json:"email"`
Mobile string `json:"mobile"`
Developers []Developer `gorm:"many2many:developer_teams"`
}
message.go
:
/models/message.go
package models
import "gorm.io/gorm"
type Message struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
TeamID int `json:"team_id"`
Title string `json:"title"`
Content string `json:"content"`
Team Team
}
I'm trying to make it such that when you enter the input fields as JSON in trigger_notification
, it sends back a JSON response that shows all the developers that are under a specific team via the mobile and email objects.
The response should look something like this:
{
team_id: "team_id",
sms: {
id: "ARANDOMID",
mobiles: ["numer1","number2"]
content: "the content of this message",
sent_at: "18:54:34 IST 2021"
},
email: {
id: "ARANDOMID",
emails: ["email1@email.com", "email2@email.com"]
title: "Used in emails for title",
content: "the content of this message",
sent_at: "18:54:34 IST 2021"
}
setup.go
:
package models
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectDatabase() {
database, err := gorm.Open(sqlite.Open("sms-go.db"), &gorm.Config{})
if err != nil {
panic("Failure to connect to database")
}
database.AutoMigrate(&Developer{})
database.AutoMigrate(&Message{})
database.AutoMigrate(&Team{})
DB = database
}
答案1
得分: 2
对于自引用的多对多关系,您需要使用与模型名称不同的字段名称,例如:
type Developer struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Full_name string `json:"full_name"`
Email string `json:"email"`
Mobile string `json:"mobile"`
// 将 `Developers []Developer` 更改为:
DevTeam []Developer `gorm:"many2many:developer_teams"`
}
请参阅 gorm.io 文档:自引用的多对多关系。
英文:
For self-referential many2many relationship you need to use a field name that is different from the model's name, for example:
type Developer struct {
gorm.Model
ID uint `json:"id" gorm:"primary_key"`
Full_name string `json:"full_name"`
Email string `json:"email"`
Mobile string `json:"mobile"`
// Change `Developers []Developer` to:
DevTeam []Developer `gorm:"many2many:developer_teams"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论