Generics 一种处理嵌入一个公共结构的所有结构类型的方法(json编组)

Generics 一种处理嵌入一个公共结构的所有结构类型的方法(json编组),generics,model-view-controller,go,struct,interface,Generics,Model View Controller,Go,Struct,Interface,我有一个有点MVC架构的gin gonic web应用程序。我创建了两个模型,它们都嵌入了一个公共结构: 类型用户结构{ ID int 名称字符串 } 类型管理结构{ 使用者 整数级 } ... { 使用者 } 现在我想将它们以json格式存储在数据库中。我想要实现的目标是只编写一个函数/方法,用于封送任何模型并将其保存到数据库中。此方法必须封送当前模型的所有字段,而不仅仅是来自用户结构,例如,用户必须封送到{id:1,name:“zhora”},而管理员将进入{id:1,name:“gena

我有一个有点MVC架构的gin gonic web应用程序。我创建了两个模型,它们都嵌入了一个公共结构:

类型用户结构{
ID int
名称字符串
}
类型管理结构{
使用者
整数级
}
... {
使用者
}
现在我想将它们以json格式存储在数据库中。我想要实现的目标是只编写一个函数/方法,用于封送任何模型并将其保存到数据库中。此方法必须封送当前模型的所有字段,而不仅仅是来自用户结构,例如,用户必须封送到
{id:1,name:“zhora”}
,而管理员将进入
{id:1,name:“gena”,level:2}

像这个:

func(i*User)Save(){
数据,err:=json.Marshal(i)
检查(错误)
如果i.ID==0{
_,err=app.DB.Exec(`INSERT-INTO-users(data)value($1)`,string(data))
}否则{
_,err=app.DB.Exec(`updateuserssetdata=$1,其中id=$2`,string(data),i.id)
}
检查(错误)
}

现在我必须将这个
func
复制/粘贴到每个模型文件中,只更改方法接收器。这可以避免吗?

您可以像这样使用一个
func Save(d接口{})

主程序包
进口(
“编码/json”
“fmt”
)
类型用户结构{
ID int
名称字符串
}
类型管理结构{
使用者
整数级
}
func main(){
保存(用户{})
保存(管理员{})
}
func Save(d接口{}){
body,err:=json.Marshal(d)
如果错误!=零{
恐慌(错误)
}
st:=字符串(正文)
fmt.Println(st)
}
输出:

{"ID":0,"Name":""}
{"ID":0,"Name":"","Level":0}
{"Id":0,"Name":""}
ID is  0
{"Id":0,"Name":"","Level":0}
ID is  0

对于您的情况,请对所有类型使用此函数:

func保存(i接口{},id int){
数据,err:=json.Marshal(i)
检查(错误)
如果id==0{
_,err=app.DB.Exec(`INSERT-INTO-users(data)value($1)`,string(data))
}否则{
_,err=app.DB.Exec(`updateuserssetdata=$1,其中id=$2`,string(data),id)
}
检查(错误)
}
这样称呼它:

u:=User{}
a:=管理员{}
保存(u,u.ID)
保存(a,a.ID)

是的,这甚至简化了对一个参数的
Save
调用:

主程序包
进口(
“编码/json”
“fmt”
)
类型模型接口{
ID()int
setID(int)
}
类型用户结构{
Id int
名称字符串
}
func(t User)ID()int{return t.ID}
func(t User)setID(id int){t.id=id}
类型管理结构{
使用者
整数级
}
func main(){
保存(用户{})
保存(管理员{})
}
func保存(d模型){
body,err:=json.Marshal(d)
如果错误!=零{
恐慌(错误)
}
st:=字符串(正文)
fmt.Println(st)
fmt.Println(“ID是”,d.ID())
}
输出:

{"ID":0,"Name":""}
{"ID":0,"Name":"","Level":0}
{"Id":0,"Name":""}
ID is  0
{"Id":0,"Name":"","Level":0}
ID is  0

现在,您可以对所有类型使用此函数:

func保存(i型){
数据,err:=json.Marshal(i)
检查(错误)
id:=i.id()
如果id==0{
_,err=app.DB.Exec(`INSERT-INTO-users(data)value($1)`,string(data))
}否则{
_,err=app.DB.Exec(`updateuserssetdata=$1,其中id=$2`,string(data),id)
}
检查(错误)
}
这样称呼它:

u:=User{}
a:=管理员{}
保存(u)
保存(a)

:

吸气剂

Go不提供对getter和setter的自动支持。有 自己提供接受者和接受者没有什么错,而且 这样做通常是合适的,但既不惯用,也没有必要 把Get放在getter的名字里。如果您有一个名为owner的字段 (小写,未报告),getter方法应称为Owner (大写,已导出),而不是GetOwner。使用大写名称表示 导出提供了钩子来区分字段和方法。A. 如果需要,setter函数很可能被称为SetOwner。两个名字 熟读:

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

@kakysha我希望这会有帮助。谢谢!非常感谢你的帮助。你的解决方案很有效,但我更进一步,用
getID()int
setID(int)
方法创建了一个接口
Model
,使
User
满足这个接口,并使用
Model
代替
interface{}
作为方法
Save(m Model)的参数
不将id作为第二个参数传递,只传递结构本身。我还需要它在
INSERT。。。正在返回id
。再次感谢!,你救了我!看到你关于getter和setter的更新。使User.ID未报告并将getID()重命名为ID(),再次感谢。出于某种原因,
golint
没有抱怨:(