介绍一个Go程序员不理解for…range容易出现的错误.
简述
for...range
是Go编程里面非常常用到的Slice和map的遍历方式,它的伪代码你懂吗?- 常常有人被踩到循环赋值,指针引用的坑的问题。
for…range遍历取值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package main
import "fmt"
type Person struct {
name string
}
func main() {
personSlice := []Person{
{"shazi"},
{"coolliuzw"},
}
var res []*Person
for _, person := range personSlice {
res = append(res, &person)
}
for _, person := range res {
fmt.Println("name-->>:", person.name)
}
}
|
输出结果:
1
2
| name-->>: coolliuzw
name-->>: coolliuzw
|
- 是不是和你的预期不太一样,为什么是这样的呢?
for range
的时候,person
只初始化了一次,理解这句话应该就知道为什么了。- 之后的遍历都是在原来遍历的基础上赋值,所有person的指针(地址)并没有变。该指针指向的是最后一次遍历的person的值,所以最后结果集中,也就都成了最后遍历的v的值
最后提一个问题?刚刚出现的问题怎么解决呢?
1
2
| for i := range personSlice {
res = append(res, &personSlice[i])
|
1
2
3
4
5
| // 哈哈,也可以考虑一下为什么这么定义person不会重复定义哦
for _, person := range personSlice {
person := person
res = append(res, &person)
}
|
总结
指针是Go、C、C++的重点支持,使用好指针对内存,GC、性能都有很大的提高。一定要理解清楚哦。