Go语言函数中的参数传递效果测试


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