为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
湖上湖 2022-03-03 16:00:06
我有一个带有某种 MVC 架构的 gin-gonic 网络应用程序。我创建了几个模型,它们都嵌入了一个通用结构:type User struct {   ID int   Name string}type Admin struct {   User   Level int}... {   User}现在我想将它们以 json 格式存储在数据库中。我想要完成的目标是只编写一个函数/方法来编组任何模型并将其保存到数据库中。此方法必须编组当前模型的所有字段,不仅来自 User 结构,例如 User 必须编组到{id: 1, name: "zhora"},而 Admin 将进入{id: 1, name: "gena", level: 2}。像这个:func (i *User) Save() {  data, err := json.Marshal(i)  check(err)  if i.ID == 0 {    _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))  } else {    _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), i.ID)  }  check(err)}现在我必须将它复制/粘贴func到每个模型文件中,只更改方法接收器。这可以避免吗?
查看完整描述

1 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您可以使用func Save(d interface{})这样的一种:


package main


import (

    "encoding/json"

    "fmt"

)


type User struct {

    ID   int

    Name string

}


type Admin struct {

    User

    Level int

}


func main() {

    Save(User{})

    Save(Admin{})

}


func Save(d interface{}) {

    body, err := json.Marshal(d)

    if err != nil {

        panic(err)

    }

    st := string(body)

    fmt.Println(st)

}

输出:


{"ID":0,"Name":""}

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

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


func Save(i interface{}, id int) {

    data, err := json.Marshal(i)

    check(err)

    if id == 0 {

        _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))

    } else {

        _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), id)

    }

    check(err)

}

并这样称呼它:


u := User{}

a := Admin{}


Save(u, u.ID)

Save(a, a.ID)

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


package main


import (

    "encoding/json"

    "fmt"

)


type Model interface {

    ID() int

    setID(int)

}


type User struct {

    Id   int

    Name string

}


func (t User) ID() int      { return t.Id }

func (t User) setID(id int) { t.Id = id }


type Admin struct {

    User

    Level int

}


func main() {

    Save(User{})

    Save(Admin{})

}


func Save(d Model) {

    body, err := json.Marshal(d)

    if err != nil {

        panic(err)

    }

    st := string(body)

    fmt.Println(st)


    fmt.Println("ID is ", d.ID())

}

输出:


{"Id":0,"Name":""}

ID is  0

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

ID is  0

现在您可以将这一功能用于所有类型:


func Save(i Model) {

    data, err := json.Marshal(i)

    check(err)

    id := i.ID()

    if id == 0 {

        _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))

    } else {

        _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), id)

    }

    check(err)

}

并这样称呼它:


u := User{}

a := Admin{}


Save(u)

Save(a)

有效围棋:


吸气剂


Go 不提供对 getter 和 setter 的自动支持。自己提供 getter 和 setter 并没有错,而且这样做通常是合适的,但是将 Get 放入 getter 的名称中既不习惯也没有必要。如果您有一个名为 owner(小写,未导出)的字段,则 getter 方法应称为 Owner(大写,已导出),而不是 GetOwner。使用大写名称进行导出提供了将字段与方法区分开来的钩子。如果需要,setter 函数可能会被称为 SetOwner。这两个名字在实践中都很好读:


owner := obj.Owner()

if owner != user {

    obj.SetOwner(user)

}


查看完整回答
反对 回复 2022-03-03
  • 1 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信