为什么使用值传入,输出的是正确的,但使用指针传入,再取值,获得的值却是一样的呢????
```go
package main
import (
"fmt"
"time"
)
func tggg(p *int) {
fmt.Printf("p = %p, v = %d\n", p, *p)
}
func tggg1(t int) {
fmt.Printf("v = %d\n", t)
}
func main() {
number := []int{1, 2, 3, 4, 5}
for _, v := range number {
go tggg1(v)
go tggg(&v)
}
time.Sleep(5*time.Second)
}
```
输出结果:
```
v = 1
p = 0xc000084010, v = 5
v = 2
p = 0xc000084010, v = 5
v = 3
p = 0xc000084010, v = 5
v = 4
p = 0xc000084010, v = 5
v = 5
p = 0xc000084010, v = 5
```
---------------------------------------时间线---------------------------
我有加了个sleep 输出就不一样了,怎么感觉从地址里取值有延时啊
```go
package main
import (
"fmt"
"time"
)
func tggg(p *int) {
fmt.Printf("p = %p, v = %d\n", p, *p)
}
func tggg1(t int) {
fmt.Printf("v = %d\n", t)
}
func main() {
number := []int{1, 2, 3, 4, 5}
for k, v := range number {
// go tggg1(v)
switch k {
case 0:
time.Sleep(1*time.Second)
go tggg(&v)
case 1:
time.Sleep(2*time.Second)
go tggg(&v)
case 2:
time.Sleep(3*time.Second)
go tggg(&v)
case 3:
time.Sleep(4*time.Second)
go tggg(&v)
case 4:
time.Sleep(5*time.Second)
go tggg(&v)
}
// go tggg(&v)
}
time.Sleep(5*time.Second)
}
```
输出结果:
```
= 0xc000084010, v = 2
p = 0xc000084010, v = 3
p = 0xc000084010, v = 4
p = 0xc000084010, v = 5
p = 0xc000084010, v = 5
```
但是为啥没有1 ,却有两个5呢?????
```先解释为什么会出现缺1,主要是主协程跑得比第一个子协程快(因为你加了sleep),而你传递的是v的内存地址,而恰巧range会自动更改v的值,从而导致你的第一个子协程在开始执行后获取v的值时候出现了这一种情况:第一个子协程获取第二圈的range的v值,第2个子协程获取第3圈的range的v值,第3个子协程获取第4圈的range的v值,第4个子协程获取第5圈的range的v值,到第五圈时候主协程的for退出但是还没执行完,同时第5个子协程被你第5圈的range创建后还没执行完,所以,接下里就是第5个子协程获取第5圈的range的v值,如何防止出现这种情况:```
### 1.将主协程延迟:
![无标题.png](https://static.studygolang.com/190925/cec29b7deb39e53d8116683b7e6d6847.png)
### 2.不要获取v的内存地址,而是获取他的值,这样在创建子协程时候就会直接获取v的值并且copy一份给子协程了,而不是获取内存地址,导致给了主协程 改变v的值的机会,从而出现不应该出现的东西
![无标题11.png](https://static.studygolang.com/190925/c41cd569252975d41dc443482fcf5bb0.png)
#### 说到底这个需要点内存基础和明白引用类型和值类型的区别
#14
更多评论
啊,我是看了https://studygolang.com/articles/23530#reply1 才知道这个的。。。
我不是很理解啊,虽然传的是指针,但是那个地址存的值不是应该实时变得吗?为啥不变啊
#2