先说清楚,在go中没有引用变量,所以更不存在什么引用传值了。
什么是引用变量吗?
在类C++语言中,你可以声明一个别名,给一个变量安上一个其他名字,我们把这称为引用变量。
#include <stdio.h>
int main() {
int a = 10;
int &b = a;
int &c = b;
printf("%p %p %p
", &a, &b, &c); // 0x7ffe114f0b14 0x7ffe114f0b14 0x7ffe114f0b14
return 0;
}
你可以看到a
,b
,c
都指向同一块内存地址,三者的值相同,当你要在不同范围内声明引用变量(即函数调用)时,此功能很有用。
go中不存在引用变量
与C++不同的是,go中的每一个变量都有着独一无二的 内存地址。
package main
import "fmt"
func main() {
var a, b, c int
fmt.Println(&a, &b, &c) // 0x1040a124 0x1040a128 0x1040a12c
}
你不可能在go程序中找到两个变量共享一块内存,但是可以让两个变量指向同一个内存。
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
。
map
和channel
是引用吗?
不是,map和channel都不是引用,如果他们是的话,下面这个例子就会输出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)
}
如果是引用变量的话,main
中的m
被传到fn
中,那么经过函数的处理m
应该已经被初始化了才对,但是可以看出fn
的处理对m
并没有影响,所以map
也不是引用。
至于map到底是什么?下篇文章将会说清楚。