栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在golang中从unsafe.Pointer指针创建数组或切片

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在golang中从unsafe.Pointer指针创建数组或切片

前言:

您应该知道:如果将指针作为

uintptr
类型的值获取,则不会阻止原始数组被垃圾回收(
uintptr
值不算作引用)。因此,使用此类值时请务必小心,不能保证它会指向有效值/存储区。

从包装报价

unsafe.Pointer

uintptr是整数,而不是引用。将Pointer转换为uintptr会创建一个没有指针语义的整数值。即使uintptr拥有某个对象的地址,垃圾回收器也不会在对象移动时更新该uintptr的值,该uintptr也不会使该对象被回收。

一般建议:

unsafe
尽可能远离包装。留在Go的类型安全中。


声明分片类型的变量,并使用不安全的转换来获取其

reflect.SliceHeader
描述符。

然后,您可以修改其字段,将指针用作

SliceHeader.Data
值,将大小用作
SliceHeader.Len
SliceHeader.Cap

完成此操作后,slice变量将指向与初始指针相同的数组。

arr := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}size := len(arr)p := uintptr(unsafe.Pointer(&arr))var data []bytesh := (*reflect.SliceHeader)(unsafe.Pointer(&data))sh.Data = psh.Len = sizesh.Cap = sizefmt.Println(data)runtime.KeepAlive(arr)

输出(在Go Playground上尝试):

[0 1 2 3 4 5 6 7 8 9]

请注意,我用过

runtime.KeepAlive()
。这是因为在获取地址
arr
并获取其长度之后,我们不再引用
arr
p
uintptr
当作参考),并且积极的GC可能会
arr
在我们准备打印之前
data
(正确地指向)删除。
arr
)。将a
runtime.KeepAlive()
放在的末尾
main()
将确保
arr
在此调用之前不会被垃圾回收。有关详细信息,请参阅InGo中的变量何时不可达?
runtime.KeepAlive()
如果指针的提供者确保不会被垃圾回收,则无需调用代码。

另外,您也可以创建

reflect.SliceHeader
带有复合文字的,并使用不安全的转换从中获取切片,如下所示:

sh := &reflect.SliceHeader{    data: p,    Len:  size,    Cap:  size,}data:= *(*[]byte)(unsafe.Pointer(sh))fmt.Println(data)runtime.KeepAlive(arr)

输出将是相同的。在Go Playground上尝试一下。

在上记录了这种可能性/用例

unsafe.Pointer
,并附带警告和警告:

(6)将reflect.SliceHeader或reflect.StringHeader数据字段与指针进行转换。

与前面的情况一样,反射数据结构SliceHeader和StringHeader将字段Data声明为uintptr,以防止调用者在不首先导入“不安全”的情况下将结果更改为任意类型。但是,这意味着SliceHeader和StringHeader仅在解释实际切片或字符串值的内容时才有效。

var s stringhdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) // case 1hdr.Data = uintptr(unsafe.Pointer(p))   // case 6 (this case)hdr.Len = n

在这种用法中,hdr.Data实际上是引用切片头中基础指针的替代方法,而不是uintptr变量本身。

通常,reflect.SliceHeader和reflect.StringHeader只能用作指向实际切片或字符串的
reflect.SliceHeader和
reflect.StringHeader,而不能用作纯结构。程序不应声明或分配这些结构类型的变量。

// INVALID: a directly-declared header will not hold Data as a

reference.
var hdr reflect.StringHeader
hdr.Data = uintptr(unsafe.Pointer(p))
hdr.Len = n
s := (string)(unsafe.Pointer(&hdr)) // p possibly already lost



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/484356.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号