Struct пуст после Json unmarshal при доступе из другого пакета - PullRequest
0 голосов
/ 05 февраля 2019

Я использую структуру Contact, которая имеет метод Load().Идея состоит в том, что Load() заполняет поля Contact данными.Данные отправляются из json, возвращаемого сервером.После загрузки я хочу иметь возможность доступа к данным на Contact.

. Я знаю, что json корректно распаковывает данные, потому что я могу распечатать данные на консоли в Load(), сразу после того, как они былиunmarshalled.Однако эти данные отсутствуют на Contact после загрузки.Поэтому, когда я создаю новый Contact и вызываю его метод Load(), его поля данных остаются пустыми, когда я обращаюсь к ним.

Это упрощенная версия моего кода (за исключением импорта для краткости):

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 Ответ

0 голосов
/ 05 февраля 2019

Contact.Load() изменяет структуру, поэтому для сохранения изменений в ней должен быть указатель получателя:

func (contact *Contact) Load() error {
    // ...
}

Все параметры (включая получателя) передаются по значению, что означает, что копия являетсясделано и функции / методы могут работать только с копией.Если получатель не является указателем, то все изменения, внесенные методом, относятся к копии, которая отбрасывается при возврате метода.

Если получатель является указателем, он также будет скопирован, но вы не хотитеизменить указатель, но указанное значение, которое будет таким же.

См. связанные / возможные дубликаты:

Мой объект не обновляется, даже если я использую указатель на типчтобы обновить его

Удалить элемент слайса в структуре

...