1、总结 :
- 所有的 Data 结构的指针地址都发生了变化,意味着所有的结构都是一块新的内存,无论是将 Data 结构传入函数内部,还是通过函数返回值传回 Data 都会发生复制行为。
- 所有的 Data 结构中的成员值都没有发生变化,原样传递,意味着所有参数都是值传递。
- Data 结构的 ptr 成员在传递过程中保持一致,表示指针在函数参数值传递中传递的只是指针值,不会复制指针指向的部分。
- 结构体A传入函数内部,会重新开辟一块内存,如0xaaa地址,将A赋值到0xaaa地址上;
- 结构体A作为返回值时,又重新开辟了一块内存,如0xbbb地址
2、一句话,总结(核心思想,记住下面的话 ):
其实,就是
- 如果实例是非全局变量的话,传入函数内部的话,肯定
重新开辟 了一块内存来保存实例的值, - 如果返回值又赋值给了
原变量 的话,地址肯定不变 的,有可能实例里的属性内容发生了变化 - 如果返回值重新赋值给
新的变量 ,地址 肯定发生变 了
3、如何减少内存的使用呢?
传递函数时,如果没有必要全部传入的话,只需要传递部分实例属性就行了,不然,会重新开辟一块新的内存,浪费内存空间
函数传递参数.jpg
4、测试用例:
代码地址:
https://github.com/xej520/learning-go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | package func5_test import ( "testing" "fmt" ) type Data struct { complax []int // 测试切片在参数传递中的效果 instance InnerData // 实例分配的innerData // 注意一下,下面的ptr的值,获取的是地址,具体地址里的值是什么,并不关心 ptr *InnerData // 将ptr声明为InnerData的指针类型 } // 代表各种结构体字段 type InnerData struct { A int } // 声明一个全局变量 var in = Data{ // 测试切片在参数传递中的效果 complax: []int{ 2, 3, 4, }, // 实例分配的innerData instance: InnerData{ A: 4, }, // 将ptr声明为InnerData的指针类型 ptr: &InnerData{ A: 6, }, } //测试,结构体作为函数参数传入 func TestPassByValue(t *testing.T) { fmt.Printf("传入函数前, 打印结构体Data实例的值: %+v ", in) fmt.Printf("传入函数前, 打印结构体Data实例中instance的地址: %p ", &in.instance) fmt.Printf("传入函数前, 打印结构体Data实例的地址: %p ", &in) fmt.Println() out := passByValue(in) fmt.Println() fmt.Printf("经过函数处理后, 打印结构体Data实例的值: %+v ", out) fmt.Printf("经过函数处理后, 打印结构体Data实例中instance的地址: %p ", &out.instance) fmt.Printf("经过函数处理后, 打印结构体Data实例的地址: %p ", &out) } //函数内部的变量,是局部变量 func passByValue(inFunc Data) Data { fmt.Printf("在函数内部, 打印结构体Data实例的值: %+v ", inFunc) fmt.Printf("在函数内部, 打印结构体Data实例中instance的地址: %p ", &inFunc.instance) fmt.Printf("在函数内部, 打印结构体Data实例的地址: %p ", &inFunc) return inFunc } |
测试结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | === RUN TestPassByValue 传入函数前, 打印结构体Data实例的值: {complax:[2 3 4] instance:{A:4} ptr:0x63a248} 传入函数前, 打印结构体Data实例中instance的地址: 0x64b758 传入函数前, 打印结构体Data实例的地址: 0x64b740 在函数内部, 打印结构体Data实例的值: {complax:[2 3 4] instance:{A:4} ptr:0x63a248} 在函数内部, 打印结构体Data实例中instance的地址: 0xc00009a348 在函数内部, 打印结构体Data实例的地址: 0xc00009a330 经过函数处理后, 打印结构体Data实例的值: {complax:[2 3 4] instance:{A:4} ptr:0x63a248} 经过函数处理后, 打印结构体Data实例中instance的地址: 0xc00009a318 经过函数处理后, 打印结构体Data实例的地址: 0xc00009a300 --- PASS: TestPassByValue (0.00s) PASS |
参考博客地址:
http://c.biancheng.net/view/54.html
?
?
?
?
?
?
微信.jpg