我有一个结构:
type user struct {
Id string
..
data_ptr *userData
}
我将片段用户存储在全球范围内:
type Hall struct {
users []user
}
var hall = Hall{} //global
最后,http处理程序:
func dataHandler(response http.ResponseWriter, request *http.Request) {
userExist, user_ptr := hall.haveUserId() //works fine
switch requestType {
case "load":
user_ptr.loadData() //data loaded and user_ptr.data_ptr is set
case "newData":
user_ptr.data_ptr = newData // <-- this is it, now previously set data_ptr == nil
那么,为什么哎呀,我的意思是我发送&#34;加载&#34;请求,它会加载数据,为data_ptr
设置user_ptr
。但是在接下来的电话中,&#34; newData&#34;请求,user_ptr.data_ptr
是nil
?
以防万一,这里是loadData()
:
func (p *user) loadData(userId) {
..
data := userData {}
p.data_ptr = &data
}
编辑: user_ptr
来自:
func (h *Hall) haveUserId(id string) (bool, *user) {
for _, u := range h.users {
if u.Id == id {
fmt.Println("UID found")
return true, &u
}
}
return false, nil
}
答案 0 :(得分:4)
这是因为您使用副本而不是切片元素本身。
在haveUserId()
函数中,for ... range
复制了它循环的元素,并返回此副本的地址。所以稍后您将修改此副本,该副本独立于切片中的值。因此,如果稍后检查切片元素中的地址,它仍将保持不变(nil
)。
可能的解决方法:返回切片元素的地址:&h.users[i]
func (h *Hall) haveUserId(id string) (bool, *user) {
for i := range h.users {
if h.users[i].Id == id {
fmt.Println("UID found")
return true, &h.users[i]
}
}
return false, nil
}
为了证明这一点,请参阅此示例:
type Point struct{ x, y int }
ps := []Point{{1, 2}, {3, 4}}
fmt.Println(ps) // Output: [{1 2} {3 4}]
for _, v := range ps {
v.x += 10 // Modifies just the copy
}
fmt.Println(ps) // Output (unchanged): [{1 2} {3 4}]
for i := range ps {
ps[i].x += 10 // Modifies value in slice
}
fmt.Println(ps) // Output (changed): [{11 2} {13 4}]
在Go Playground上尝试。