Pointer is a variable that stores the memory address of another variable.
Asterisk is used to declare a pointer type and de-reference a pointer, ampersand is used to obtain the memory address of a variable.
Pointers are used to efficiently share or modify data without copying it, and to directly access or update the original value of a variable.
When you copy a slice in Go, both the original and the copy share the same value, so modifying one affects the other. That's because slices contain pointers to an underlying array under the hood.
func main() {
var slice = []int32{1, 2, 3}
var sliceCopy = slice
sliceCopy[2] = 4
fmt.Println(slice) // [1, 2, 4]
fmt.Println(sliceCopy) // [1, 2, 4]
}
Using pointers avoids copying data, saving memory, and enhancing performance by directly accessing and modifying the original variable. Example below demonstrates that each array have different memory address.
package main
import (
"fmt"
)
func main() {
var thing1 = [5]float64{1, 2, 3, 4, 5}
fmt.Printf("\nThe memory location of the thing1 array is: %p", &thing1)
var result [5]float64 = square(thing1)
fmt.Printf("\nThe result is: %v", result)
fmt.Printf("\nThe value of thing1 is: %v", thing1)
}
// Accept the array by value (creates a copy)
func square(thing2 [5]float64) [5]float64 {
fmt.Printf("\nThe memory location of the thing2 array is: %p", &thing2)
for i := range thing2 {
thing2[i] = thing2[i] * thing2[i] // Modifies the copy, not the original
}
return thing2 // Returns the modified copy
}
The better example from the one above using pointer is modifying thing2 without affecting thing1 so they’ll have same memory address (same array) instead of double memory usage (two separate arrays).
package main
import (
"fmt"
)
func main() {
var thing1 = [5]float64{1, 2, 3, 4, 5}
fmt.Printf("\nThe memory location of the thing1 array is: %p", &thing1)
// Pass a pointer to the array
var result [5]float64 = square(&thing1)
fmt.Printf("\nThe result is: %v", result)
fmt.Printf("\nThe value of thing1 is: %v", thing1)
}
// Accept a pointer to the array and return a new array
func square(thing2 *[5]float64) [5]float64 {
fmt.Printf("\nThe memory location of the thing2 array is: %p", thing2)
for i := range thing2 {
thing2[i] = thing2[i] * thing2[i] // Modify the original array
}
return *thing2 // Return a copy of the modified array
}
Struct pointers in Go are automatically dereferenced. For example, w.balance works instead of (*w).balance.
type Wallet struct {
balance int
}
func (w *Wallet) Balance() int {
return w.balance // same as (*w).balance
}
Go copies values when you pass them to functions/methods, so if you're writing a function that needs to mutate state you'll need it to take a pointer to the thing you want to change.
nil or you might raise a runtime exception - the compiler won't help you here.