I am practicing by developing a web server written in Go, using Gqlgen and Gorm (postgres dialect).
I started by describing the model of my User:
# dbm.User{}
type User struct {
BaseModel
Email string `gorm:"not null;unique_index:idx_email"`
UserID *string // External user ID
Name *string
NickName *string
FirstName *string
LastName *string
Location *string `gorm:"size:1048"`
Description *string `gorm:"size:1048"`
}
In this case, from what I understand, it is nice to use pointers for certain values in my struct because they can evaluate to <nil> when there is no value attached to it. Whereas if I use no pointers, an int will be 0 if no value is attached to it. Alright, this makes sense...if I am not wrong...
However, the difficulty that I face now, is when getting this value out of a Gorm operation on the DB:
dbRecord := &dbm.User{}
db = db.Where(whereEmail, email).Find(&dbRecord)
fmt.Println("dbRecord:", dbRecord)
// Prints:
// dbRecord: &{{def90b3c-93ff-40f0-8d33-6320dddbe3f2 2019-10-01 14:16:34.365395 +0200 CEST 2019-10-01 14:16:34.365395 +0200 CEST} [email protected] <nil> 0xc0000a1cb0 0xc0000a1cd0 0xc0000a1cc0 <nil> 0xc0000a1cf0 0xc0000a1ce0}
This code queries a User where email is "[email protected]", and obviously some fields in the struct point to the actual address of the value. This makes sense, but it is very annoying if I want to read this data. Is there a conventional way of reading this data?
What I tried is to is to convert this struct into a GQL struct (which was autogenerated by GQLgen):
# gqlm.User{}
type User struct {
ID string `json:"id"`
Email string `json:"email"`
UserID *string `json:"userId"`
Name *string `json:"name"`
FirstName *string `json:"firstName"`
LastName *string `json:"lastName"`
NickName *string `json:"nickName"`
Description *string `json:"description"`
Location *string `json:"location"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt"`
}
But again, I get the addresses when I want the values, which makes sense.
So the only way I found is to create a new custom struct customUser, Marshal the data from Gorm, then Unmarshal it into my customUser struct:
type customUser struct {
ID string `json:"id"`
Email string `json:"email"`
UserID string `json:"userId"`
Name string `json:"name"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
NickName string `json:"nickName"`
Description string `json:"description"`
Location string `json:"location"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
bs, _ := json.Marshal(record)
var s = string(bs)
newRecord := &customUser{}
bs = []byte(s) // This is maybe not necessary
err = json.Unmarshal(bs, newRecord)
if err != nil {
fmt.Println(err)
}
fmt.Printf("record: %+v\n", newRecord)
// I now get the right format: record: &{ID:def90b3c-93ff-40f0-8d33-6320dddbe3f2 Email:[email protected] UserID: Name:frer FirstName:fwef LastName: NickName:trgt Description:werfergh rthrt hr Location:wfwf CreatedAt:2019-10-01 14:16:34.365395 +0200 CEST UpdatedAt:2019-10-01 14:16:34.365395 +0200 CEST}
But this seems so overkilled, and lots of effort if I need to create such struct everytime I need to read data from the DB. Is this the way to go? Or do you know a more convenient way?
Name stringinstead ofName *stringin my Gorm User struct? I thought that using pointers there is actually conventional, because it avoids confusion when a field is empty and that it returns a value anyway""and a user with namenil, both indicate a user with no name, there is no confusion, it's just that one is more difficult to use then the other, right? There are legitimate cases where""is semantically not the same asnil, however there is less of those cases then cases where those two can be considered the same, in my opinion.*Nickname. What is annyoing here?