8

我有一个 Go 对象,我想保持它在内存中的地址不变。在 C# 中,可以将对象的位置固定在内存中。有没有办法在 Go 中做到这一点?

4

2 回答 2

9

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.

于 2012-08-23T19:29:30.247 回答
0

tl;博士不 - 但除非你试图做一些不寻常的事情,否则没关系。

值得注意的是,接受的答案部分不正确。

不能保证对象不会被移动——无论是在堆栈上还是在 Go 堆上——但只要你不使用unsafe它对你来说并不重要,因为 Go 运行时会透明地更新你的指针,以防万一对象被移动。

如果您使用 OTOHunsafe来获取uintptr、调用原始系统调用、执行 CGO 调用或以其他方式公开地址(例如oldAddr := fmt.Sprintf("%p", &foo))等,您应该知道地址可以更改,并且编译器和运行时都不会神奇地为您修补东西。

虽然目前标准的 Go 编译器只移动堆栈上的对象(例如,当需要调整 goroutine 堆栈的大小时),但 Go 语言规范中没有任何内容阻止不同的实现在 Go 堆上移动对象。

虽然没有明确支持将对象固定在堆栈或 Go 堆中,但有一个推荐的解决方法:在 Go 堆之外手动分配内存(例如 via mmap),并使用终结器在所有对它的引用后自动释放该分配被丢弃。这种方法的好处是在 Go 堆之外手动分配的内存永远不会被 Go 运行时移动,所以它的地址永远不会改变,但它仍然会在不再需要时自动释放,所以它不会泄漏.

于 2021-05-27T06:48:11.183 回答