如何在 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
抱歉我的英语不好。
我正在使用 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
抱歉我的英语不好。