如何在golang中原子存储和加载接口?



我想编写一些这样的代码:

var myValue interface{}
func GetMyValue() interface{} {
    return atomic.Load(myValue)
}
func StoreMyValue(newValue interface{}) {
    atomic.Store(myValue, newValue)
}

似乎我可以使用 loadUintptr(addr *uintptr)(val uintptr) and and storeuintptr(addr *uintptr *uintptr,val uintptr,val uintptr),但我不知道如何在 uintptr 之间转换, unsafe.pointer interface {}

如果我这样做:

var V interface{}
func F(v interface{}) {
    p := unsafe.Pointer(&V)
    atomic.StorePointer(&p, unsafe.Pointer(&v))
}
func main() {
    V = 1
    F(2)
    fmt.Println(V)
}

V 将始终为1

如果我没记错的话,您想要原子值。您可以将其存储和获取值以原子为单位(签名是interface{},但应该在其中放置相同的类型)。它像您想做的那样在引擎盖下做一些不安全的指针。

来自文档的样本:

var config Value // holds current server configuration
// Create initial config value and store into config.
config.Store(loadConfig())
go func() {
        // Reload config every 10 seconds
        // and update config value with the new version.
        for {
                time.Sleep(10 * time.Second)
                config.Store(loadConfig())
        }
}()
// Create worker goroutines that handle incoming requests
// using the latest config value.
for i := 0; i < 10; i++ {
        go func() {
                for r := range requests() {
                        c := config.Load()
                        // Handle request r using config c.
                        _, _ = r, c
                }
        }()
}

这是一种使用atomic.StorePointeratomic.LoadPointer的方法(基于您的示例):

package main
import (
    "fmt"
    "sync/atomic"
    "unsafe"
)
var addr unsafe.Pointer
func GetMyValue() *interface{} {
    return (*interface{})(atomic.LoadPointer(&addr))
}
func StoreMyValue(newValue *interface{}) {
    atomic.StorePointer(&addr, unsafe.Pointer(newValue))
}
func main() {
    var i interface{}
    i = 1
    StoreMyValue(&i)
    fmt.Println("before:", *GetMyValue())
    i = 2
    StoreMyValue(&i)
    fmt.Println("after", *GetMyValue())
}

游乐场链接

请注意,这不会使您的对象线程安全。只有指针被原子存储/加载。另外,我会避免使用interface{},并在可能的情况下更喜欢混凝土类型。

作为使用'any'(interface{})的替代方案,GO 1.19(Q3 2022)在sync/atomic软件包中带有新类型,使其更易于使用原子值,例如原子。int64和 atomic.Pointer[T]

这比使用atomic.StorePointer更容易。
这来自第50860期。sync/atomic:添加键入的原子值。
和CL 381317

Pointer[T]还避免使用Unsafe.pointer在呼叫站点进行转换。

您无法执行此操作。

您将必须用互斥士克保护商店/负载。界面的内部表示未指定语言,并且可能(可能是)可以通过包装原子来处理。

最新更新