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)
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)
}