返回介绍

传值与传指针

发布于 2024-10-12 12:35:53 字数 1855 浏览 0 评论 0 收藏 0

传一个参数值到被调用函数里面时,实际上是传了这个值的一份 copy,当在被调用函数中修改参数值的时候,调用函数中相应实参不会发生任何变化,因为数值变化只作用在 copy 上。

为了验证上面的说法,来看一个例子

package main
import "fmt"
//简单的一个函数,实现了参数+1 的操作
func add1(a int) int {
    a = a+1 // 改变了 a 的值
    return a //返回一个新值
}
func main() {
    x := 3
    fmt.Println("x = ", x)  // 应该输出 "x = 3"
    x1 := add1(x)  //调用 add1(x)
    fmt.Println("x+1 = ", x1) // 应该输出"x+1 = 4"
    fmt.Println("x = ", x)    // 应该输出"x = 3"
}

虽然调用了 add1 函数,并且在 add1 中执行 a = a+1 操作,但是上面例子中 x 变量的值没有发生变化

理由很简单:因为当调用 add1 的时候, add1 接收的参数其实是 x 的 copy,而不是 x 本身。

如果真的需要传这个 x 本身,该怎么办呢?

这就牵扯到了所谓的指针。变量在内存中是存放于一定地址上的,修改变量实际是修改变量地址处的内存。只有 add1 函数知道 x 变量所在的地址,才能修改 x 变量的值。所以需要将 x 所在地址 &x 传入函数,并将函数的参数的类型由 int 改为 *int ,即改为指针类型,才能在函数中修改 x 变量的值。此时参数仍然是按 copy 传递的,只是 copy 的是一个指针。请看下面的例子

package main
import "fmt"
//简单的一个函数,实现了参数+1 的操作
func add1(a *int) int { // 请注意,
    *a = *a+1 // 修改了 a 的值
    return *a // 返回新值
}
func main() {
    x := 3
    fmt.Println("x = ", x)  // 应该输出 "x = 3"
    x1 := add1(&x)  // 调用 add1(&x) 传 x 的地址
    fmt.Println("x+1 = ", x1) // 应该输出 "x+1 = 4"
    fmt.Println("x = ", x)    // 应该输出 "x = 4"
}

这样,就达到了修改 x 的目的。那么到底传指针有什么好处呢?

  • 传指针使得多个函数能操作同一个对象。

  • 传指针比较轻量级 (8bytes),只是传内存地址,可以用指针传递体积大的结构体。如果用参数值传递的话,在每次 copy 上面就会花费相对较多的系统开销(内存和时间)。所以当要传递大的结构体的时候,用指针是一个明智的选择。

  • Go 语言中 channelslicemap 这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针。(注:若函数需改变 slice 的长度,则仍需要取地址传递指针)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文