我有一个 Go 对象,我想保持它在内存中的地址不变。在 C# 中,可以将对象的位置固定在内存中。有没有办法在 Go 中做到这一点?
2 回答
An object on which you keep a reference won't move. There is no handle or indirection, and the address you get is permanent.
From the documentation :
Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns
When you set a variable, you can read this address using the &
operator, and you can pass it.
tl;博士不 - 但除非你试图做一些不寻常的事情,否则没关系。
值得注意的是,接受的答案部分不正确。
不能保证对象不会被移动——无论是在堆栈上还是在 Go 堆上——但只要你不使用unsafe
它对你来说并不重要,因为 Go 运行时会透明地更新你的指针,以防万一对象被移动。
如果您使用 OTOHunsafe
来获取uintptr
、调用原始系统调用、执行 CGO 调用或以其他方式公开地址(例如oldAddr := fmt.Sprintf("%p", &foo)
)等,您应该知道地址可以更改,并且编译器和运行时都不会神奇地为您修补东西。
虽然目前标准的 Go 编译器只移动堆栈上的对象(例如,当需要调整 goroutine 堆栈的大小时),但 Go 语言规范中没有任何内容阻止不同的实现在 Go 堆上移动对象。
虽然没有明确支持将对象固定在堆栈或 Go 堆中,但有一个推荐的解决方法:在 Go 堆之外手动分配内存(例如 via mmap
),并使用终结器在所有对它的引用后自动释放该分配被丢弃。这种方法的好处是在 Go 堆之外手动分配的内存永远不会被 Go 运行时移动,所以它的地址永远不会改变,但它仍然会在不再需要时自动释放,所以它不会泄漏.