如何修改嵌套结构的属性值

时间:2019-11-21 04:39:05

标签: pointers go struct

我正在尝试在Go中修改嵌套结构的变量的值。基本上,我想修改RsvpString属性,但是GetRsvp()似乎返回Rsvp的值而不是引用,因此,当我修改其属性值时,它不会反映在Event实例。

测试在下面。

type Event struct {
    Rsvps     []Rsvp `json:"rsvps"`
}

type Rsvp struct {
    UserId          string `json:"userId"`
    RsvpString      string `json:"rsvp"`
}

func (e *Event) GetRsvp(userId string) (rsvp *Rsvp, err error) {
    for _, element := range e.Rsvps {
        if element.UserId == userId {
            return &element, nil
        }
    }
    return &Rsvp{}, fmt.Errorf("could not find RSVP based on UserID")
}

func (e *Event) UpdateExistingRsvp(userId string, rsvpString string) {
    rsvp, err := e.GetRsvp(userId)
    if err == nil {
        rsvp.RsvpString = rsvpString
    }
}

这是测试代码:

func TestEvent_UpdateExistingRsvp(t *testing.T) {
    e := Event{[]Rsvp{
        {Name:      "Bill",
            UserId:    "bill",
            Rsvp:      "yes"}}}

    e.UpdateExistingRsvp("bill", "no")
    assert.Equal(t, "no", e.Rsvps[0].Rsvp, "RSVP should be switched to no") // fails
}

2 个答案:

答案 0 :(得分:3)

GetRsvp返回的是循环变量的地址,而不是数组中元素的地址。要解决:

    for i, element := range e.Rsvps {
        if element.UserId == userId {
            return &e.Rsvps[i], nil
        }
    }

循环变量保留e.Rsvps [i]的副本,并且在每次迭代时都会被覆盖。如果返回循环变量的地址,则返回该副本的地址。

答案 1 :(得分:1)

在切片上范围内时,每次迭代都会返回两个值。第一个是索引,第二个是该索引处的元素的副本。

因此从技术上讲,您正在尝试修改Rsvp的副本。 而是返回索引,并从GetRsvp()方法进行更新。

func (e *Event) GetRsvp(userId string) (int, error) {
    for index , element := range e.Rsvps {
        if element.UserId == userId {
            return index, nil
        }
    }
    return -1 , fmt.Errorf("could not find RSVP based on UserID")
}

func (e *Event) UpdateExistingRsvp(userId string, rsvpString string) {
    index, err := e.GetRsvp(userId)

    if err != nil || index == -1  {
        fmt.Println("no such user")
    }
    e.Rsvps[index].RsvpString = rsvpString
}
相关问题