指针传递与值传递
严格地说,go方法或函数只有一种传递方式,那就是值传递。每次将一个变量作为参数传递时,都会创建一个新的变量副本并将其传递给所调用的函数或方法。副本分配在不同的内存地址。
在指针传递变量的情况下,将创建指向相同内存地址的新副本。为了感受它们之间的差异,我们来看看它是如何工作的。
值传递
package mainimport "fmt"type person struct { firstname string lastname string}func changename(p person) { p.firstname = "bob"}func main() { person := person { firstname: "alice", lastname: "dow", } changename(person) fmt.println(person)}
运行代码将得到以下输出:
{alice dow}
请注意,即使函数changename将firstname更改为“bob”,但更改不会影响main函数中的变量person。发生这种情况是因为函数changename修改了变量person的一个副本,而不是person本身。
指针传递
package mainimport "fmt"type person struct { firstname string lastname string}func changename(p *person) { p.firstname = "bob"}func main() { person := person { firstname: "alice", lastname: "dow", } changename(&person) fmt.println(person)}
运行代码将得到以下输出:
{bob dow}
在这种情况下,函数main中的变量person在函数changename中被修改。发生这种情况是因为&person和p是存储在相同内存地址的相同结构的两个不同指针。
变量不能被修改
我们没有其他的选择,只能通过值传递。所以这个变量不能在下游修改。反之亦然,如果变量被期望修改,它必须通过指针传递。
变量是一个大的结构
如果变量是一个大的结构,性能是一个问题,最好是通过指针传递变量。这样可以避免在内存中复制整个结构。
变量是一个map或slice
go中的map和slice是引用类型,应该通过值传递。
值传递通常开销更小
即使go看起来有点像c,它的编译器工作方式也不同。c的类比并不总是和go一起工作。在go中值传递可能比指针传递开销更小。发生这种情况是因为go使用逃逸分析来确定变量是否可以安全地分配到函数的栈帧上,这可能比在堆上分配变量开销小的多。通过值传递可以简化go中的逃逸分析,并为变量提供更好的分配机会。
总结
指针传递和值传递的区别
1、指针传递传递的是一个地址,而非地址中的数据,传递数据较少,效率较值传递高,一般情况能用指针传递不用值传递。
2、指针传递时,调用函数中对指针所指向空间数据的修改会影响到调用者,因为他们指向的是同一块区域,指传递就不会影响到调用者的数据。
相关推荐:golang教程
以上就是golang指针传递和值传递的区别是什么?的详细内容。
