gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:58:36 26 4
gpt4 key购买 nike

我有一个带有 MVC 架构的 gin-gonic 网络应用程序。我创建了几个模型,它们都嵌入了一个通用结构:

type User struct {
ID int
Name string
}

type Admin struct {
User
Level int
}

... {
User
}

现在我想将它们以 json 格式存储在数据库中。我想要实现的目标是只编写一个函数/方法,它将编码任何模型并将其保存到数据库中。此方法必须编码当前模型的所有字段,而不仅仅是来自用户结构,例如用户必须编码到 {id: 1, name: "zhora"},而管理员将进入 {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 复制/粘贴到每个模型文件,只更改方法接收器。这可以避免吗?

最佳答案

您可以像这样使用一个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)

Effective Go :

Getters

Go doesn't provide automatic support for getters and setters. There's nothing wrong with providing getters and setters yourself, and it's often appropriate to do so, but it's neither idiomatic nor necessary to put Get into the getter's name. If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner. The use of upper-case names for export provides the hook to discriminate the field from the method. A setter function, if needed, will likely be called SetOwner. Both names read well in practice:

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

关于generics - 一种处理嵌入一个通用结构的所有结构类型的方法(json 编码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39131886/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com