安全吗?

(*TeamData)(unSafe.Poite(&Team.Id))

示例代码:


func testTrans() []*TeamData {
    teams := createTeams()
    teamDatas := make([]*TeamData, 0, len(teams))
    for _, team := range teams {
        // is this safe?
        teamDatas = append(teamDatas, (*TeamData)(unSafe.Poite(&Team.Id)))
    }
    return teamDatas
}

// ??
teams := testTrans()

teams := testTrans()数组的成员是否会被垃圾收集?

There are many structs and many fields returned through grpc and their definitions are the same as the local definitions, so I want to use this more efficient way((*TeamData)(unSafe.Poite(&Team.Id))), but I don't know if there will be any risks.

完整示例: https://go.dev/play/p/q3gwp2mERvj

推荐答案

unsafe.Pointer的文档介绍了受支持的用途.尤其是:

(1)将*t1转换为指向*t2的指针.

假设T2不大于T1,并且两者共享一个 等效内存布局,此转换允许重新解释数据 一种类型的数据作为另一种类型的数据.

GO的垃圾回收器识别内部指针,直到没有对该块的剩余引用时才会收集原始分配. 因此,当存在对*TeamData的引用时,较大的分配(在您的示例中为GrpcRetTeam)将被固定.

另一个关键的考虑因素是alignment of the struct fields.例如:

type Parent struct {
    A uint8
    B uint8
    // 6 bytes of padding to align C.
    C uint64
}

type Bad struct {
    B uint8
    // 7 bytes of padding to align C.
    C uint64
}

在这种情况下,使用不安全从Parent中提取Bad是无效的,因为内存布局不同.

在大多数情况下,除非需要满足功能或性能要求,否则最好避免unsafe.Pointer个技巧.通常可以重构代码以最大限度地减少分配.

如果您必须使用unsafe来满足性能要求-- 我建议使用reflect包实现一个测试,以确保内存对齐/布局对子 struct 有效.

Go相关问答推荐

如何修复Go中调用GetRawInputDeviceInfA Windows API函数时的错误?

有没有办法通过Go cmdline或IDE(IntelliJ)找出我的 struct 实现了什么接口?

如何将文件从AWS S3存储桶复制到Azure BLOB存储

exec的可执行决议.命令+路径

Golang Gorm Fiber - 如何将定义为别名的名称发送到索引模板?

正则表达式模式,确保至少一个字符与其他条件一起存在

Golang chromedp Dockerfile

最长连续重复的字符golang

regex.ReplaceAll 但如果替换则添加相同数量的字符

Wire google Inject with multi return from provider 函数

如何模仿联合类型

具有两个或多个模型的 GORM 查询

Golang并发写入多个文件

Go:等待多个通道的性能损失

具有近似约束的函数值导致的实例化失败

如何正确为 Go 中的值设置多种类型?

递归数据 struct 解组在 Go Lang Protobuf 中给出错误无法解析无效的线格式数据

GOLANG 如何使用 http.FileServer 从模板目录加载某个 html 文件

Golang 'defer' 导致发送(接收)API 响应延迟

全局记录(across packages)