go语言的值传递和指针传递

指针传递与值传递

严格地说,go方法或函数只有一种传递方式,那就是值传递。每次将一个变量作为参数传递时,都会创建一个新的变量副本并将其传递给所调用的函数或方法。副本分配在不同的内存地址。

在指针传递变量的情况下,将创建指向相同内存地址的新副本。为了感受它们之间的差异,我们来看看它是如何工作的。

值传递

package main

import "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 main

import "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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值