前言
在Go中如果使用过map和channel,就会发现把map和channel作为函数参数传递,不需要在函数形参里对map和channel加指针标记*就可以在函数体内改变外部map和channel的值。
这会给人一种错觉:map和channel难道是类似C++的引用变量,函数传参的时候使用的是引用传递?
比如下面的例子:
// example1.go package main import "fmt" func changeMap(data map[string]interface{}) { data["c"] = 3 } func main() { counter := map[string]interface{}{"a": 1, "b": 2} fmt.Println("begin:", counter) changeMap(counter) fmt.Println("after:", counter) }
程序运行的结果是:
begin: map[a:1 b:2] after: map[a:1 b:2 c:3]
上面的例子里,函数changeMap改变了外部的map类型counter的值。
那map传参是使用的引用传递么?带着这个问题,我们先回顾下什么是引用变量和引用传递。
什么是引用变量(reference variable)和引用传递(pass-by-reference)
我们先回顾下C++里的引用变量和引用传递。看下面的例子:
// example2.cpp #include <iostream> using namespace std; /*函数changeValue使用引用传递*/ void changeValue(int &n) { n = 2; } int main() { int a = 1; /* b是引用变量,引用的是变量a */ int &b = a; cout << "a=" << a << " address:" << &a << endl; cout << "b=" << b << " address:" << &b << endl; /* 调用changeValue会改变外部实参a的值 */ changeValue(a); cout << "a=" << a << " address:" << &a << endl; cout << "b=" << b << " address:" << &b << endl; }
程序的运行结果是:
a=1 address:0x7ffee7aa776c b=1 address:0x7ffee7aa776c a=2 address:0x7ffee7aa776c b=2 address:0x7ffee7aa776c
在这个例子里,变量b是引用变量,引用的是变量a。引用变量就好比是原变量的一个别名,引用变量和引用传递的特点如下&#x