一种处理所有嵌入一个公共结构(json编组)的结构类型的方法 [英] One method to handle all the struct types that embed one common struct (json marshalling)
问题描述
$ b
type User struct {
ID int
名称字符串
}
类型管理结构{
用户
级别int
}
... {
User
}
现在我想要以json格式将它们存储在数据库中。我想要完成的目标是仅编写一个函数/方法来编组任何模型,并将其保存到数据库中。此方法必须编组当前模型的所有字段,而不仅仅是来自User结构,例如用户必须编入 {id:1,name:zhora}
,而管理员将进入 {id:1,name:gena ,level:2}
。
像这样:
func(i * User)Save(){
data,err:= json.Marshal(i)
check(err)
if 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),i.ID)
}
check(err)
}
现在我必须复制/粘贴 func
到每个模型文件,只更改方法接收器。这可以避免吗?
您可以使用一个 func Save(d interface {}) code>像这样:
package main
import (
encoding / json
fmt
)
类型用户结构{
ID int
名称字符串
}
类型结构{
用户
级别int
}
func main(){
Save(User { })
保存(Admin {})
}
func保存(d接口{}){
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:=用户{}
a:=管理员{}
保存(u,u.ID)
保存(a,a.ID)
是的,这甚至简化了对 Save的调用添加到一个参数中:
package main
import(
encoding / 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}
类型管理结构{
User
Level int
$ b $ func main(){
保存(用户{})
保存(管理{})
}
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为0
{Id:0,Name:,Level:0}
ID为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))
} e lse {
_,err = app.DB.Exec(`UPDATE users SET data = $ 1 WHERE id = $ 2`,string(data),id)
}
check(err)
}
并且像这样调用它:
u:= User {}
a:=管理员{}
保存(u)
保存(a)
Getters
Go不为getter和setter提供自动支持。有
自己提供getter和setter没什么问题,而且
通常适合这样做,但是它不是习惯用法,也不需要
来获取getter的名字。如果您有一个名为owner
(小写,未导出)的字段,则应将getter方法称为Owner
(大写,已导出),而不是GetOwner。
导出的大写名称的使用提供了区分该字段与方法的钩子。如果需要,
setter函数可能会被称为SetOwner。两个名字
在练习中都很好的阅读:
owner:= obj.Owner()
=用户{
obj.SetOwner(用户)
}
I have a gin-gonic web app with somewhat MVC architecture. I created a couple of models, all of them embed one common struct:
type User struct {
ID int
Name string
}
type Admin struct {
User
Level int
}
... {
User
}
Now I want to store them in database in json format. The goal I want to accomplish is to code only one function/method that will marshal any model and will save save it into DB. This method must marshal all the fields of current model, not only from User struct, e.g. User must be marshaled into {id: 1, name: "zhora"}
, while Admin will go into {id: 1, name: "gena", level: 2}
.
Like this one:
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)
}
Right now I have to copy/paste this func
to every model file, changing only method receiver. Can this be avoided?
You may use one func Save(d interface{})
like this:
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)
}
output:
{"ID":0,"Name":""}
{"ID":0,"Name":"","Level":0}
for your case, use this one function for all types:
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)
}
And call it like this:
u := User{}
a := Admin{}
Save(u, u.ID)
Save(a, a.ID)
And Yes, this is even simplifies call to Save
to one parameter:
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())
}
output:
{"Id":0,"Name":""}
ID is 0
{"Id":0,"Name":"","Level":0}
ID is 0
Now You may use this one function for all types:
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)
}
And call it like this:
u := User{}
a := Admin{}
Save(u)
Save(a)
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) }
这篇关于一种处理所有嵌入一个公共结构(json编组)的结构类型的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!