跨原子存储进行原子存储,然后在例程之间行为异常

I am trying to store a map as unsafe.Pointer and trying to retrieve it later. Below is the code snippet:

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
", 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()

}

When Set(), executes, it prints the contents of m.ptr correctly. However, when we do a Get(), it returns nil. This looks totally un-expected to me. I am using go 1.11.6

The output of the above program is:

The pointer loaded is: 0x40c130
Why is this pointer value nil?

Because the Set method has a value receiver, the receiver value and any changes to the value are discarded when the method returns. Fix the problem by using pointer receivers.

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

The Get method must also use a pointer receiver to prevent a data race on the copy of the receiver argument.

The Set method stores the address of argument myMap, not the address of m in main. This may or may not be a problem depending on how the application uses MapHolder.