• Go语言中的值传递和引用传递 附: 内存地址分析


    在学习Go语言函数部分遇到了引用传递和值传递,与C颇为类似,浅谈一下自己对Go语言中的值传递和引用传递的理解。

    一、数组—值传递

    我们用Go语言中的数组作为样例,来理解值传递的过程。

    代码

    1. package main
    2. import "fmt"
    3. func main() {
    4. arr1 := [4]int{1, 2, 3, 4}
    5. fmt.Printf("arr1-p: %p\n", &arr1)
    6. fmt.Printf("arr1[0]-p: %p\n", &arr1[0])
    7. fmt.Println("arr1-1: ", arr1)
    8. update(arr1)
    9. fmt.Println("arr1-2: ", arr1)
    10. }
    11. func update(arr2 [4]int) {
    12. fmt.Println("arr2-1: ", arr2)
    13. arr2[0] = 5
    14. fmt.Println("arr2-2: ", arr2)
    15. fmt.Printf("arr2-p: %p\n", &arr2)
    16. fmt.Printf("arr2[0]-p: %p\n", &arr2[0])
    17. }

    结果

    1. arr1-p: 0xc0000141a0
    2. arr1[0]-p: 0xc0000141a0
    3. arr1-1: [1 2 3 4]
    4. arr2-1: [1 2 3 4]
    5. arr2-2: [5 2 3 4]
    6. arr2-p: 0xc0000141e0
    7. arr2[0]-p: 0xc0000141e0
    8. arr1-2: [1 2 3 4]

    通过运行,我们可以看到,在Go语言中对于数组传递,属于值传递,当然基本类型以及结构体在Go中也是数值传递。我们画图来理解上述结果~

     

    从输出结果我们可以看出,arr1 和 arr2 对指向的地址与数组中的首个元素的地址相一致,说明变量 arr1 和 arr2 对应的就是数组中首元素的地址。在函数传递过程中,arr2 的数据是从 arr1 赋值或者拷贝过来的,分别存在于内存的不同空间中,所以修改 arr2 并不会对 arr1 产生影响。

    补充:这里我们了解到,arr1 的地址和索引为 0 的元素的地址相同,也就是 arr1 的与索引为 0 的元素在内存的同一位置,arr1 所对应的数值为 [1 2 3 4],同理 arr2 也是如此。

    对于值传递来说,在传递过程中,传递的是数据的副本,在其它函数中修改数据,并不会对原始数据产生影响。

    二、切片—引用传递

    我们将Go语言中与数组非常相似的切片类型作为样例,来理解引用传递的过程。

    代码

    1. package main
    2. import "fmt"
    3. func main() {
    4. s1 := []int{1, 2, 3, 4}
    5. fmt.Println("s1:", s1)
    6. update2(s1)
    7. fmt.Println("s1:", s1)
    8. fmt.Printf("s1: %p\n", s1)
    9. fmt.Printf("s1-p: %p\n", &s1)
    10. }
    11. func update2(s2 []int) {
    12. fmt.Println("s2: ", s2)
    13. s2[0] = 5
    14. fmt.Println("s2: ", s2)
    15. fmt.Printf("s2: %p\n", s2)
    16. fmt.Printf("s2-p: %p\n", &s2)
    17. }

    结果

    1. s1: [1 2 3 4]
    2. s2: [1 2 3 4]
    3. s2: [5 2 3 4]
    4. s2: 0xc0000141a0
    5. s2-p: 0xc0000080a8
    6. s1: [5 2 3 4]
    7. s1: 0xc0000141a0
    8. s1-p: 0xc000008078

    通过运行结果我们可以看到,切片在Go中属于引用传递,当然还有很多引用传递的类型,比如 map、chan等等。我们看图理解~

    分析运行结果,我们能够得知,不论是 s1 还是 s2 都是指向内存中的同一地址,所以当 s2 在操作索引为 0 的数据内容时,会使得原始数据产生改变,也就是 s1 原本的数据发生变化。

    补充:这里变量 s1 和 s2 的内存地址并不相同,一个是 0xc000008078,另一个是 0xc0000080a8,但是相同的是,变量 s1 和 s2 的内存地址存储的内容一致,都是切片首元素的地址,也就是索引为 0 的元素的地址。

    那么对于引用传递来说,变量在内存中的存放在一定的地址上,修改变量实际上就是修改变量所在地址处的内容。

  • 相关阅读:
    442-C++基础语法(111-120)
    编程学:关于同类词的等长拼写问题
    Java 并发之 AQS 详解(上)
    [python-大语言模型]从浅到深一系列学习笔记记录
    精神心理科医生:抑郁症正在好转的5种表现
    美食杰项目 -- 菜品信息(五)
    Redis最佳实践(上)
    《鸿蒙生态应用开发白皮书》读后感
    java框架-Spring-容器创建过程
    配置禁止生成可执行文件-火绒法
  • 原文地址:https://blog.csdn.net/weixin_52772307/article/details/128105081