package main

type theIntType int
func main()  {
   var val = 23
   var p int
   _ = first(val, &p)
   _ = second(val, &p)

}
func first(val int, p *int) (*theIntType) {
   *p = val
   return (*theIntType)(p)
}

func second(val int, p *int) (*theIntType) {
   p = &val
   return (*theIntType)(p)
}

以上这段代码,两个函数的区别是什么呢?

first函数中,是将val的值赋值给p变量的值,所以p变量的地址没有发生变化。

second函数中,是将val的地址赋值给p变量的地址,所以p变量的地址发生了变化。

在调用函数的时候,由于val是值传递,所以发生了copy动作,因此在first和second中的val变量的地址与函数调用前的地址是不一样的。而由于参数p传递的是指针,所以没有发生copy事件。

记住一句话:指针类型就是指向一个值得内存地址。即可以粗暴的认为指针即地址。

增加一篇文章跳链:Go 的值拷贝代价,里面提到了不建议采用双迭代变量的遍历方式。因为每次迭代都发生了元素复制动作,造成了一定的开销(原译文:如果元素类型是大值类型, 我们还应该尝试避免使用两次迭代变量形式来迭代数组和切片元素, 因为每个元素值都将被复制到迭代过程中的第二个迭代变量(译注: for range 中的 v).)