I have a Go object whose address in memory I would like to keep constant. in C# one can pin an object's location in memory. Is there a way to do this in Go?
2 Answers
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.

- 372,613
- 87
- 782
- 758
-
9To clarify: Go's GC is not a compacting GC. It will never move live objects around. – Lily Ballard Aug 23 '12 at 19:41
-
1Here's a blogpost (disclaimer: which I wrote) that looks into Go's escape analysis a bit more closely: http://www.scvalex.net/posts/29/ – scvalex May 03 '13 at 12:09
-
1Stack variable can be moved after Go 1.3, see https://play.golang.org/p/mxZdSK1dcS6 – youfu Mar 26 '18 at 02:48
-
1While the current GC in the go runtime does not move objects in the heap, there is no guarantee that future versions won't move objects on the heap, or that alternate implementations don't. Also objects on the stack can be moved. See my answer below for details. – CAFxX Jun 25 '21 at 09:28
-
This promise is apparently not strong enough for `cgo`, which will not let you pass to C a pointer to Go memory that itself contains a pointer to Go memory (e.g. you cannot pass a pointer to the type `struct { []byte }` to C). – kbolino Mar 11 '22 at 15:41
tl;dr no - but it does not matter unless you're trying to do something unusual.
Worth noting that the accepted answer is partially incorrect.
There is no guarantee that objects are not moved - either on the stack or on the Go heap - but as long as you don't use unsafe
this will not matter to you because the Go runtime will take care of transparently updating your pointers in case an object is moved.
If OTOH you use unsafe
to obtain a uintptr
, invoke raw syscalls, perform CGO calls, or otherwise expose the address (e.g. oldAddr := fmt.Sprintf("%p", &foo)
), etc. you should be aware that addresses can change, and that nor compiler nor runtime will magically patch things for you.
While currently the standard Go compiler only moves objects on the stack (e.g. when a goroutine stack needs to be resized), there is nothing in the Go language specification that prevents a different implementation from moving objects on the Go heap.
While there is (yet) no explicit support for pinning objects in the stack or in the Go heap, there is a recommended workaround: allocate manually the memory outside of the Go heap (e.g. via mmap
) and using finalizers to automatically free that allocation once all references to it are dropped. The benefit of this approach is that memory allocated manually outside of the Go heap will never be moved by the Go runtime, so its address will never change, but it will still be deallocated automatically when it's not needed anymore, so it can't leak.

- 28,060
- 6
- 41
- 66
-
1There is also [a proposal](https://github.com/golang/go/issues/46787) to develop an explicit pinning mechanism. – kbolino Mar 11 '22 at 15:39
-