(译) Go 语言中没有引用传递

谢烟客 · · 2345 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

原文链接:There is no pass-by-reference in Go

我之前关于指针的那篇帖 引起了很多关于引用传递的争议。这篇帖子算是对这些争议的回应吧。

首先要清楚的是:Go 语言中没有引用变量,所以 Go 语言就没有引用传递的函数调用的语法。

什么是引用变量?

在像 C++ 这样的语言中你可以给一个已经存在的变量定义一个别名,这个别名就被称为引用变量。

#include <stdio.h>

int main() {
        int a = 10;
        int &b = a;
        int &c = b;

        printf("%p %p %p\n", &a, &b, &c); // 0x7ffe114f0b14 0x7ffe114f0b14 0x7ffe114f0b14
        return 0;
}

你可以看到上面 a、b、c 都指向了相同的内存地址,向 a 写入数据将会更改 b、c 的内容。这当你想在不同作用域(即函数调用)里定义引用变量的时候就显得十分的关键。

Go 语言中并没有引用变量

与 C++ 不同,Go 语言中每一个定义的变量都占据一个唯一的内存地址

dave 原来的例子我觉得可能跟上面 C++ 的例子对比不是很突出,所以我改了一下

package main

import (
    "fmt"
)

func main() {
    var a int
    var b = &a
    var c = &a

    fmt.Println(&a, &b, &c) //0xc0420361d0 0xc04204e018 0xc04204e020
}

在 Go 语言中,不可能创建 2 个变量而这 2 个变量却拥有相同的内存地址。Go 语言是允许创建 2 个变量它们的内容是同一个指向相同地址的指针,但是这与两个变量共享同一个内存地址完全是两回事。

package main

import "fmt"

func main() {
        var a int
        var b, c = &a, &a
        fmt.Println(b, c)   // 0x1040a124 0x1040a124
        fmt.Println(&b, &c) // 0x1040c108 0x1040c110
}

在这个例子中 b、c 持有的相同的值是 a 的地址,然而 b、c 他们自己的存储则存储在各自唯一的地址中的,更新 b 的内容 是不会对 c 的内容产生影响的。

但 Maps 与 Channels 是引用变量总该对了吧?

错! Maps 与 Channels 依然不是引用变量。如果他们是引用变量,那么下面这段程序将打印 false.

package main

import "fmt"

func fn(m map[int]int) {
        m = make(map[int]int)
}

func main() {
        var m map[int]int
        fn(m)
        fmt.Println(m == nil)
}

如果 m 像 C++ 那样是引用变量,定义在 fn 中的 m 与 定义在 main 中的 m 应该占用同一个内存地址,但是因为在 fn 中的赋值操作,并没有影响到 main 中 m 的值,所以我们可以看出 map 并不是引用变量。

结论:

Go 语言中并没有引用传递,因为在 Go 语言中连引用变量也没有。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:谢烟客

查看原文:(译) Go 语言中没有引用传递

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2345 次点击  ∙  1 赞  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传