问题
I'm am using a struct Contact
that has a Load()
method. The idea is that Load()
populates Contact
's fields with data. The data is unmarshalled from json returned by a server. Once loaded, I want to be able to access the data on Contact
.
I know that the json is unmarshalling correctly because I can print the data to the console within Load()
, immediately after it has been unmarshalled. However, this data is not present on Contact
once it has been loaded. So when I create a new Contact
and call its Load()
method, its data fields are still empty when I go to access them.
This is a simplified version of my code (minus imports for brevity):
package main
func main() {
client := &http.Client{}
mp := myPackage.NewContact("1234", client)
if err := mp.Load(); err != nil {
log.Println(err)
}
// prints empty string
log.Println(mp.EmailOptIn)
}
// myPackage
package myPackage
type Contact struct {
ID string
client *http.Client
EmailOptIn string `json:"marketing_optin"`
}
func NewContact(ID string, client *http.Client) *Contact {
return &Contact{
ID: ID,
client: client,
}
}
func (contact Contact) Load() error {
req, err := http.NewRequest("GET", "https://anAPI.com/"+contact.ID, nil)
if err != nil {
log.Println(err)
}
resp, err := contact.client.Do(req)
if err != nil {
log.Println(err)
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
body, _ := ioutil.ReadAll(resp.Body)
if err = json.Unmarshal(body, &contact); err != nil {
log.Println("Can't unmarshall: " + err.Error())
}
// prints "Opted_in"
log.Println(contact.EmailOptIn)
return nil
}
return errors.New("oh dear")
}
回答1:
Contact.Load()
modifies the struct, so in order to retain the changes, it must have a pointer receiver:
func (contact *Contact) Load() error {
// ...
}
All parameters (including the receiver) are passed by value which means a copy is made and the functions / methods can only operate on the copy. If the receiver is not a pointer then all changes the method makes are on the copy which is discarded when the method returns.
If the receiver is a pointer, it will also be copied, but you don't want to modify the pointer but the pointed value, which will be the same.
See related / possible duplicates:
My object is not updated even if I use the pointer to a type to update it
Remove an element of a slice in a struct
来源:https://stackoverflow.com/questions/54532448/struct-is-empty-after-json-unmarshal-when-accessed-by-another-package