我有一个Go对象,其内存中的地址我想保持不变。在C#中,可以将对象的位置固定在内存中。有没有办法在Go中做到这一点?
答案 0 :(得分:6)
您保留引用的对象不会移动。没有句柄或间接,你得到的地址是永久性的。
请注意,与C不同,返回a的地址是完全可以的 局部变量;与变量关联的存储仍然存在 函数返回后
设置变量时,可以使用&
运算符读取此地址,然后传递它。
答案 1 :(得分:0)
tl;dr no - 但没关系,除非你想做一些不寻常的事情。
值得注意的是,接受的答案部分不正确。
不能保证对象不会被移动——无论是在堆栈上还是在 Go 堆上——但只要你不使用 unsafe
,这对你来说无关紧要,因为 Go 运行时会负责在移动对象时透明地更新您的指针。
如果 OTOH 您使用 unsafe
获取 uintptr
、调用原始系统调用、执行 CGO 调用或以其他方式公开地址(例如 oldAddr := fmt.Sprintf("%p", &foo)
)等,您应该意识到地址可以更改,而且编译器和运行时都不会为您神奇地修补内容。
虽然目前标准 Go 编译器只移动堆栈上的对象(例如,当需要调整 goroutine 堆栈的大小时),但 Go 语言规范中没有任何内容阻止不同的实现在 Go 堆上移动对象。
>虽然没有明确支持在堆栈或 Go 堆中固定对象,但有一个 recommended 解决方法:手动分配 Go 堆外的内存(例如通过 mmap
)和一旦对它的所有引用都被删除,使用终结器自动释放该分配。这种方法的好处是在 Go 堆外手动分配的内存永远不会被 Go 运行时移动,所以它的地址永远不会改变,但它仍然会在不再需要时自动释放,所以它不会泄漏.