• golang sync.Map 在函数传参时默认是值传递


    概要

    今天改了一段代码,调用函数时把一个 sync.Map 类型的变量作为传参,在函数内部修改 sync.Map 变量的值,发现函数处理完成后,外部的变量没有修改,后来发现 sync.Map 是一个普通的结构体,跟所有的结构体一样,golang 在把结构体类型作为函数传参时,都是值传递,即创建参数的一个副本,然后传递给函数。这也就意味着,如果你在函数内部修改了这个副本的值,那么原始的值是不会被影响的。

    验证过程

    函数参数类型为 *sync.Map

    从运行结果来看,函数内部的修改影响了原始变量。

    1. func main() {
    2. var result sync.Map
    3. result.Store(10, 11)
    4. result.Range(func(key, value any) bool {
    5. fmt.Printf("key=%v val=%v\n", key, value)
    6. return true // 返回 false 则表示停止迭代
    7. })
    8. fmt.Println("---------------------------")
    9. GetTaskCountValueMap(&result) // 传的是指针类型
    10. fmt.Println("---------------------------")
    11. result.Range(func(key, value any) bool {
    12. fmt.Printf("key=%v val=%v\n", key, value)
    13. return true
    14. })
    15. }
    16. func GetTaskCountValueMap(result *sync.Map) {
    17. for i := 0; i < 3; i++ {
    18. result.Store(i, i+1)
    19. }
    20. result.Range(func(key, value any) bool {
    21. fmt.Printf("key=%v val=%v\n", key, value)
    22. return true
    23. })
    24. }

    输出结果

    1. key=10 val=11
    2. ---------------------------
    3. key=0 val=1
    4. key=1 val=2
    5. key=2 val=3
    6. key=10 val=11
    7. ---------------------------
    8. key=10 val=11
    9. key=0 val=1
    10. key=1 val=2
    11. key=2 val=3

    函数传参类型为 sync.Map

    从运行结果来看,函数内部的修改不会影响原始变量。

    1. func main() {
    2. var result sync.Map
    3. result.Store(10, 11)
    4. result.Range(func(key, value any) bool {
    5. fmt.Printf("key=%v val=%v\n", key, value)
    6. return true // 返回 false 则表示停止迭代
    7. })
    8. fmt.Println("---------------------------")
    9. GetTaskCountValueMap(result) // 传的是普通结构体类型
    10. fmt.Println("---------------------------")
    11. result.Range(func(key, value any) bool {
    12. fmt.Printf("key=%v val=%v\n", key, value)
    13. return true
    14. })
    15. }
    16. func GetTaskCountValueMap(result sync.Map) {
    17. for i := 0; i < 3; i++ {
    18. result.Store(i, i+1)
    19. }
    20. result.Range(func(key, value any) bool {
    21. fmt.Printf("key=%v val=%v\n", key, value)
    22. return true
    23. })
    24. }

    输出结果

    1. key=10 val=11
    2. ---------------------------
    3. key=10 val=11
    4. key=0 val=1
    5. key=1 val=2
    6. key=2 val=3
    7. ---------------------------
    8. key=10 val=11

    golang 函数传参提醒

    结构体、数组和基本数据类型都是值传递

    在Go语言中,无论是结构体还是基本数据类型,当他们作为函数参数传递时,都是值传递。如果在函数内部修改了副本的值,原始的值是不会被影响。

    切片、map 是引用传递

    切片看起来是被作为值传递,但实际上切片(slice)的数据结构包含了指向底层数组的指针。这就意味着,当你将切片传递给函数时,虽然它是传的值(也就是切片自身的数据结构被复制),但是复制的切片和原始的切片依然共享同一个底层数组。因此,如果你在函数中修改了复制的切片中的元素,原始切片相对应的元素也会被修改。

    跟切片类似,map 传递的也是对底层数据结构的引用

  • 相关阅读:
    人机智能的逻辑哲学论
    多系统架构设计思考
    【新知实验室-TRTC开发】实时音视频之web端云监工系统(Vue3+Element plus+TS+Pinia)
    0动态规划中等 LeetCode467. 环绕字符串中唯一的子字符串
    在您的下一个项目中选择 Golang 和 Node.js 之间的抉择
    Spring Boot 生成二维码
    目标检测算法——YOLOv5/YOLOv7改进之结合NAMAttention
    Influence on Social media(素论+思维)
    k8s 配置资源管理
    论文阅读之Reasoning Implicit Sentiment with Chain-of-Thought Prompting
  • 原文地址:https://blog.csdn.net/qq_41767116/article/details/132683407