首页 > 解决方案 > Go atomic store 后跟 atomic load 在例程中表现异常

问题描述

我正在尝试将地图存储为不安全的。指针并尝试稍后检索它。下面是代码片段:

package main

import (
    "fmt"
    "sync/atomic"
    "unsafe"
)

type MapHolder struct {
    ptr unsafe.Pointer
}

func (m MapHolder) Set(myMap map[string]int64) {
    atomic.StorePointer(&m.ptr, unsafe.Pointer(&myMap))
    fmt.Printf("The pointer value is: %v\n", atomic.LoadPointer(&m.ptr))
}

func (m MapHolder) Get() map[string]int64 {
    ptr := atomic.LoadPointer(&m.ptr)
    if ptr == nil {
        fmt.Printf("Why is this pointer value nil?")
        return nil
    } else {
        return *(*map[string]int64)(ptr)
    }
}

func main() {
    var m MapHolder
    test := make(map[string]int64)
    test["hello"] = 1
    m.Set(test)
    m.Get()

}

Set(), 执行时,它会m.ptr正确打印 的内容。但是,当我们执行 a 时Get(),它返回 nil。这看起来完全出乎我的意料。我正在使用 go 1.11.6

上述程序的输出是:

The pointer loaded is: 0x40c130

为什么这个指针值为零?

标签: goatomic

解决方案


因为该Set方法有一个值接收器,所以当方法返回时,接收器值和对该值的任何更改都将被丢弃。通过使用指针接收器解决问题。

func (m *MapHolder) Set(myMap map[string]int64) { ... }
func (m *MapHolder) Get() map[string]int64 { ... }

Get方法还必须使用指针接收器来防止接收器参数副本上的数据竞争。

Set方法存储参数的地址myMap,而不是min的地址main。这可能是也可能不是问题,具体取决于应用程序如何使用MapHolder.


推荐阅读