What is a Pointer?
In Go, a pointer is a variable that** stores the memory address** of another variable. Instead of holding a value directly, it points to the location where the value is stored.
Syntax
var x int = 10 var p *int = &x // p is a pointer to x
- &x: address-of operator — gets the memory address of variable x.
- *p: dereference operator — gets the value from the address p is pointing to.
Why Use Pointers?
- To share data across function calls without copying.
- To modify variables inside functions.
- To build data structures like linked lists, trees, etc.
- To optimize memory usage and performance by avoiding unnecessary copies.
Declaring and Using Pointers
var a int = 42 var p *int = &a fmt.Println("Value of a:", a) // 42 fmt.Println("Address of a:", &a) fmt.Println("Value of p:", p) // address of a fmt.Println("Value at p:", *p) // 42
Pointer Zero Value
The zero value of a pointer is nil.
var p *int fmt.Println(p) // <nil>
Always check for nil before dereferencing a pointer:
if p != nil { fmt.Println(*p) }
Passing Pointers to Functions
By Value (copy)
func increment(n int) { n++ }
This won't affect the original value.
By Pointer (reference)
func incrementPtr(n *int) { *n++ } x := 5 incrementPtr(&x) fmt.Println(x) // 6
Returning Pointers from Functions
It's safe to return pointers to local variables in Go — the compiler allocates them on the heap if necessary.
func createPointer() *int { x := 100 return &x }
Structs and Pointers
Value Receiver
type User struct { Name string } func (u User) Update(name string) { u.Name = name // Doesn't affect the original }
Pointer Receiver
func (u *User) Update(name string) { u.Name = name // Modifies the original }
Calling pointer receivers on values (and vice versa)
Go automatically converts between values and pointers when calling methods:
u := User{} u.Update("Alice") // works even if Update expects *User
Pointers and Arrays/Slices
Arrays are value types
func modifyArray(arr [3]int) { arr[0] = 100 }
Won't affect original array.
Use a pointer to modify array
func modifyArrayPtr(arr *[3]int) { arr[0] = 100 }
Slices behave like pointers internally
You can modify slice contents without using explicit pointers:
func modifySlice(s []int) { s[0] = 100 // modifies original slice }
Pointers to Pointers
Go supports pointers to pointers, but they’re rarely needed in idiomatic Go.
var x int = 10 var p *int = &x var pp **int = &p fmt.Println(**pp) // 10
Interface and Pointer Subtleties
Value vs Pointer receivers in interfaces
type Printer interface { Print() } type Data struct{} func (d Data) Print() { fmt.Println("Value") } func (d *Data) Print() { fmt.Println("Pointer") } func main() { var d Data var p Printer = &d // works // var q Printer = d // doesn't work if only pointer receiver is defined }
Always ensure your receiver type matches your intended interface use.
Pointers and new Keyword
new(Type) allocates zeroed storage and returns a pointer.
p := new(int) // *int, initialized to 0 *p = 10
Equivalent to:
var x int p := &x
Pointers and Garbage Collection
Go has garbage collection. You don’t need to free memory manually. Once a pointer is no longer referenced, Go will reclaim the memory.
Best Practices
- Use pointers to avoid copying large structs.
- Use pointer receivers if your method modifies the receiver or avoids copying.
- Avoid pointer-to-interface — use interfaces directly.
- Be careful with nil — always check before dereferencing.
- Prefer slices, maps, and channels over manual pointer-heavy code when possible.
- Avoid using pointers with basic types (like int, bool) unless necessary.
Common Mistakes
Mistake | Explanation |
---|---|
Dereferencing a nil pointer | Causes runtime panic. Always check for nil . |
Using a pointer to a value that goes out of scope in a goroutine | Safe in Go, but understand escape analysis. |
Modifying value instead of pointer in struct method | Use pointer receiver if modification is needed. |
Pointer to interface | Avoid — interface already holds type and value. |
Pointer Comparison
a := 100 b := 100 p1 := &a p2 := &a p3 := &b fmt.Println(p1 == p2) // true fmt.Println(p1 == p3) // false
Pointers are equal if they point to the same memory address.
Example: Swap Function
func swap(a, b *int) { *a, *b = *b, *a } x, y := 1, 2 swap(&x, &y) fmt.Println(x, y) // 2, 1
Top comments (0)