赞
踩
我在刚开始学习golang的时候,被值传递和引用传递困扰了一段时间,因为我之前是学习Java的,深受Java面向对象思想的影响,转成golang的时候就会想不通结构体等类型(看起来像是Java中自己定义的类),为什么会是值传递,所以总结一篇文章来通过例子简单分析一下这个问题。
先说结论:golang中都是采用值传递,即拷贝传递,也就是深拷贝。没有引用传递。之所有有些看起来像是引用传递的场景,是因为Golang中存在着引用类型,如slice、map、channel、function、pointer这些天生就是指针的类型,在传递的时候是复制的地址。引用类型作为参数时,称为浅拷贝,形参改变,实参数跟随变化。因为传递的是地址,形参和实参都指向同一块地址。(切片是引用类型,数组是值类型)切片和数组的区别
package main import( "fmt" ) func main(){ //map m := make(map[int]string) m[0] = "a" m[1] = "b" changeMap(m) fmt.Printf("map:%+v", m) //输出 map:map[0:aaa 1:b] fmt.Println() //array var a = [2]string{"a", "b"} changeArray(a) fmt.Printf("array:%+v", a) //输出array:[a b] fmt.Println() //slice var s = []string{"a", "b"} changeSlice(s) fmt.Printf("slice:%+v", s) //输出slice:[aaa b] } func changeMap(m map[int]string) { m[0] = "aaa" } func changeArray(a [2]string) { a[0] = "aaa" } func changeSlice(s []string) { s[0] = "aaa" }
通过上面的例子可以看出来map和slice都是引用类型,即函数内部是可以改变参数的值的。而array是值类型,不管函数内部如何改变参数,都是改变的拷贝值,并未对原值进行处理。
所以,golang中除了特定的几个指针类型之外,其他的所有类型,包括自己创建的结构体都是深层复制,即值类型。像是结构体,不像Java中只是把指针赋值给接收的变量,而是新开辟了一块内存空间,把所有的属性复制过去了,创建了一个一模一样的结构体。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。