Pointers in Go
External
Internal
TODO
Further reading:
- https://medium.com/@meeusdylan/when-to-use-pointers-in-go-44c15fe04eac
- https://www.ardanlabs.com/blog/2013/07/understanding-pointers-and-memory.html
- https://go.dev/doc/faq#Pointers
Overview
A pointer is a data type that represents a virtual address in memory, usually the address of a location in memory that is referred by a variable.
A pointer can be declared as such:
var aPtr *int // a pointer to an int
It can also be implicitly declared using the short variable declaration and the the referencing operator inside functions:
a := 10
aPtr := &a
aPtr
is a pointer that contains the memory address that points to the memory location associated with the variable a
. Changing the memory value using a syntax that involves the pointer will surface in the value of the variable:
*aPtr = 20
println(a) // will display 20
Once a value is assigned to a pointer, with the exception of nil
, Go guarantees that the thing being posted to will continue to be valid for the life time of the pointer. This allows for a pattern when what looks like a stack variable can be allocated inside a function, and a pointer to it returned outside the function. The pointer will remain valid even if the stack is unwound, the compiler will arrange for the memory location holding the value of i to be valid after the function returns:
func makeInt() *int {
i := 10
return &i
}
The pointer data type comes with two operators: &
(the referencing operator), and *
(the dereferencing operator).
Displaying Pointers
To display the value at memory address stored in the pointer, must dereference:
fmt.Printf("%d\n", *aPtr)
To display the memory address stored in the pointer in a hexadecimal notation, with the "0x" prefix, use %p
or %v
, they are equivalent for pointers:
fmt.Printf("%p\n", aPtr)
fmt.Printf("%v\n", aPtr) // same thing
This will print:
0xc000012080
For more details on the pointer, including the type of the data it points to, use:
fmt.Printf("%#v\n", aPtr)
This will print:
(*int)(0xc000012080)
Pointers can be also represented using the "%X"
format specifier, which displays the pointer in base 16, upper case characters, without the "0x" prefix:
fmt.Printf("%X\n", aPtr)
This will print:
C000094018
Pointer Variable Name
Do we use someNamePtr
or someName
?
Also see:
The Referencing Operator &
The referencing operator (the ampersand operator) returns an address, also known as a "reference", from a variable. &
should be read as "address of ...". It works with variables and also with literals. The syntax &user{name:"Bill"}
where user
is a struct
is legal. The address is represented internally as an instance of type pointer
. The address points to the location in memory where the instance associated with the "referenced" variable is stored.
&<variable-name>
color := "blue"
pointerToColor := &color
println(pointerToColor) // prints "0xc000058720"
The Dereferencing Operator *
The dereferencing operator (star operator) takes a pointer and returns the value in memory the pointer's address points toward. The variable must contain a pointer type instance, otherwise the code will not compile. The value thus exposed can be read or written.
*<pointer-name>
color := "blue"
pointerToColor := &color
println(*pointerToColor) // prints "blue"
*pointerToColor = "red"
println(color) // prints "red"