开门见山,在golang中,for range
中,接收到的item
用的是同一个地址,因为for range创建了每个元素的副本,而不是直接返回每个元素的引用,也就是说,以下代码将会不符合预期:
package main
import "fmt"
type A struct {
AA string `json:"aa"`
}
type B struct {
AA *string `json:"aa"`
}
func main() {
arr := []A{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}
res := make([]*B, 0)
for i, item := range arr {
fmt.Printf("item: %p, AA:%p, index:%v\n", &item, &item.AA, i)
res = append(res, &B{AA: &item.AA})
}
for _, b := range res {
fmt.Printf("%v ", *b.AA)
}
}
输出:
item: 0xc000116210, AA:0xc000116210, index:0
item: 0xc000116210, AA:0xc000116210, index:1
item: 0xc000116210, AA:0xc000116210, index:2
item: 0xc000116210, AA:0xc000116210, index:3
item: 0xc000116210, AA:0xc000116210, index:4
5 5 5 5 5
是的没错,最终res的值是555,这里有点反常识
因为for range
每次遍历的时候,都拷贝了一份到item
里面,并且item的指针永远指向同一个,因此,最终他们的值都是5
如何解决?很简单,直接访问slice中的元素而非访问拷贝的元素即可:
func main() {
arr := []A{{"1"}, {"2"}, {"3"}, {"4"}, {"5"}}
res := make([]*B, 0)
//for i, item := range arr {
// fmt.Printf("item: %p, AA:%p, index:%v\n", &item, &item.AA, i)
// res = append(res, &B{AA: &item.AA})
//}
for i, _ := range arr {
res = append(res, &B{AA: &arr[i].AA})
}
for _, b := range res {
fmt.Printf("%v ", *b.AA)
}
}
输出:
1 2 3 4 5
3 条评论
想想你的文章写的特别好https://www.jiwenlaw.com/
不错不错,我喜欢看
叼茂SEO.bfbikes.com