如何在 Go 中获取指向 Interface{} 的底层值的指针

How to get a pointer to the underlying value of an Interface{} in Go

我正在使用 cgo 与 Go 中的 C 代码进行交互,我需要使用指向 Interface{} 对象中的基础值的指针来调用 C 函数。该值将是任何原子原始类型(不包括 complex64/complex128} 或 string.

我希望我能够做这样的事情来获得 ptr 的地址作为 unsafe.Pointer:

unsafe.Pointer(reflect.ValueOf(ptr).UnsafeAddr())

但这会导致恐慌,因为该值无法寻址。

与此类似的问题是 Take address of value inside an interface,但这个问题不同,因为在这种情况下,已知该值将始终是上面指定的类型之一(最多 64 位), 我只需要将这个值赋给一个 C 函数。请注意,有多个 C 函数,将被调用的函数因不同的不相关参数而异。

我也尝试使用类型切换语句来解决这个问题,但是我发现即使在类型断言完成后我也无法获取值的地址。我能够将值分配给临时副本,然后获取这些副本的地址,但我宁愿尽可能避免制作这些副本。

interface{} 有自己的结构:

type eface struct {
    typ *rtype
    val unsafe.Pointer
}

您无法直接或通过链接访问 rtype,另一方面,即使您将复制整个 rtype,它也可能在将来更改(弃用)。

但问题是你可以用 unsafe.Pointer 替换指针类型(它可以是任何其他具有相同大小的东西,但指针是非常惯用的,因为每种类型都有自己的 pointer):

type eface struct {
    typ, val unsafe.Pointer
} 

所以,现在我们可以得到eface中包含的值:

func some_func(arg interface{}) {
   passed_value := (*eface)(unsafe.Pointer(&arg)).val
   *(*byte)(passed_value) = 'b'
}

some_var := byte('a')

fmt.Println(string(some_var)) // 'a'

some_func(some_var)
fmt.Println(string(some_var)) // 'a', it didn't changed, just because it was copied

some_func(&some_var)
fmt.Println(string(some_var)) // 'b'

您可能还会在我的存储库中看到更多用法: https://github.com/LaevusDexter/fast-cast

抱歉我的英语不好。