先说结论:无论是java还是go,都只有值传递,没有引用传递。
所谓值传递就是实参通过拷贝一份内容传递给形参,引用传递是实参将引用的对象在堆中的地址传递给形参,形参改变会影响到实参。
先以java举例:
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
这段代码传递的是基本类型,执行结果如下
a = 20
b = 10
a = 10
b = 20
可以看到传递基本类型时,形参(a, b)的改变并没有影响到实参(a, b)
再继续看下面的案例
public class Animal {
private String type;
public Animal(String type){
this.type = type;
}
public String getType() {
return type;
}
}
public static void main(String[] args) {
Animal dog = new Animal("dog"); Animal cat = new Animal("cat"); swap(dog, cat); System.out.println("dog:" + dog.getType()); System.out.println("cat:" + cat.getType());}
public static void swap(Animal dog, Animal cat) { Animal temp = dog; dog = cat; cat = temp; System.out.println("dog:" + dog.getType()); System.out.println("cat:" + cat.getType());}
这段代码传递的是引用类型,执行结果如下
dog:cat
cat:dog
dog:dog
cat:cat
可以看到,形参的改变并没有影响到实参,所以即使传递引用类型,java依然是值传递。
而传递的这个值其实是实参的拷贝地址,指向的都是同一个对象,swap方法里交换也只是实参拷贝两个地址之间的交换,并不会影响到真正的实参,入下图所示:
再看一下go语言中
func main(){
student := &Student{
name: "a",
}
teacher := &Teacher{
name: "b",
}
fmt.Println(&student)
fmt.Println(&teacher)
Swap(student, teacher)
}
type Student struct{
name string
}
type Teacher struct {
name string
}
func Swap(student *Student, teacher *Teacher) {
fmt.Println(&student)
fmt.Println(&teacher)
}
我们直接打印指针变量地址,结果如下:
0xc000012028
0xc000012030
0xc000012040
0xc000012048
可以看到传递过程中,地址发生了变化,这说明传递的是一份拷贝,所以go也是值传递。