Golang-基于地址计算字段索引

Golang-基于地址计算字段索引,go,Go,基于地址偏移量(独立于平台/编译器)计算结构字段索引是否安全 编辑 也许这个偏移词让这个问题有点混乱。当运行上述代码时,地址空间正在增长。我想知道的是,结构字段是否按照其定义的顺序分配。安全吗?好吧,让我在这里停止。您正在使用一个名为“不安全”的软件包 “假设没有对垃圾收集器之类的东西进行根本性的更改,这通常能起作用吗?”是的,可能 从unsafe文档中的OffsetOf: Offsetof返回所表示字段的结构内的偏移量 按v,其形式必须为structValue.field。换句话说,它 返回结

基于地址偏移量(独立于平台/编译器)计算结构字段索引是否安全

编辑

也许这个偏移词让这个问题有点混乱。当运行上述代码时,地址空间正在增长。我想知道的是,结构字段是否按照其定义的顺序分配。

安全吗?好吧,让我在这里停止。您正在使用一个名为“不安全”的软件包

“假设没有对垃圾收集器之类的东西进行根本性的更改,这通常能起作用吗?”是的,可能

unsafe
文档中的
OffsetOf

Offsetof返回所表示字段的结构内的偏移量 按v,其形式必须为structValue.field。换句话说,它 返回结构的开始和结束之间的字节数 场的开始

换句话说,它保证考虑对齐等问题
unsafe.Pointer(uintpttr(&t)+unsafe.OffsetOf(t.F1))
保证是指向
t
特定实例的
F1
字段的实际不安全地址的实际不安全指针

您仍然必须非常小心
不安全的
,不安全的指针通常不算作垃圾收集目的的对象“引用”。因此,如果您对该对象的唯一引用是指向该字段的不安全指针。。。奇怪的事情可能会发生。此外,有人说要实现“压缩GC”,这意味着在垃圾收集上内存可能会被洗牌,这意味着除非您锁定对象(将与压缩GC一起添加),否则不安全的指针可能会在您不知道的情况下自动失效(当然,常规指针将保持不变)

如果你确定你会保留一个对它的引用,并且你对将来完全破坏你的代码的更改没有意见,那就去做吧。我的意思是,绝对确保您需要使用不安全的,但如果您认为这是解决问题的最佳或唯一可能的解决方案,请在您接受这些风险的情况下继续使用

编辑:至于“内存订单”业务。好吧,我只是说我在规范中找不到一个保证结构按字段顺序排列的引用。也就是说,某些事情会让。。。我们应该说。。。如果不是的话,那就没什么意义了

因此,不要在超技术意义上“依赖它”,但对于任何主流的Go编译器,您都可以确信字段是按内存顺序排列的——所有关于单词对齐和打包的常见警告都会带来

也许这个偏移词让这个问题有点混乱。当运行上述代码时,地址空间正在增长。我想知道的是,结构字段是否按照其定义的顺序分配

一般来说,这应该是正确的,但要注意这样的极端情况:

type foo struct {
    a int
    b [0]byte
    c int
}
而且,从技术上讲,Go不能保证这一点。我看不出任何标准Go实现会改变字段顺序的原因。但是请注意,Go运行时的一些非标准实现(例如,一些将Go代码编译为JavaScript的实现)没有将结构实现为连续的内存位置,其中
不安全.Offsetof
的概念变得毫无意义。据我所知,这些实现没有提供
不安全的
包,因此您的代码无论如何都不会编译


TL;DR:是的。

(删除了我最初的评论——我误读了问题中的代码。)你的例子没有按照定义的顺序分配字段,编译器可以想象重新排列字段(将两个
字节
字段相邻移动,而不是将每个字段保留在两个
int
s之间,这样就需要更少的填充)但我同意这不太可能+1@twotwotwo这确实是可能的。如果你想要一个明确的答案,我建议你直接问邮件列表。从经验上看,6g不打包结构,从搜索结果来看,几乎没有任何类型的编译器这样做,所以+1是你的答案,只是出于理论上的好奇,@twtwtwo两个你通常不应该假设未指明的事情总是像现在这样,但在这种特殊情况下,你可能可以。对。我想我们只是用不同的方式表达相同的想法
type foo struct {
    a int
    b [0]byte
    c int
}