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, a pointer points to a memory location where the value is stored.
Think of it like this:
-
Normal variable → value holder
-
Pointer → address holder that leads to the value
Declaring and Using Pointers
You declare a pointer by using the *
symbol.
var p *int
-
p
is now a pointer to an integer (int
). -
It holds the address of an integer, not the integer itself.
Getting the Address of a Variable
Use the &
operator to get the address of a variable
x := 42
p := &x // p points to x
Now:
-
p
holds the address ofx
-
*p
gives you access to the value at that address
Dereferencing a Pointer
Use *
again to dereference the pointer — meaning "go to the address and fetch the value."
fmt.Println(*p) // prints 42
You can also modify the value through the pointer:
*p = 100
fmt.Println(x) // prints 100
Because p
points to x
, changing *p
also changes x
!
Why Use Pointers?
There are several reasons why pointers are important:
Reason | Explanation |
---|---|
Efficiency | Avoid copying large data structures (e.g., structs). |
Mutability | Allow functions to modify passed-in variables. |
Data Sharing | Share and update common resources without duplication. |
Pointers and Functions
Without pointers, Go functions get a copy of the argument:
func changeValue(val int) {
val = 100
}
x := 10
changeValue(x)
fmt.Println(x) // prints 10 (not changed!)
But with pointers:
func changeValue(p *int) {
*p = 100
}
x := 10
changeValue(&x)
fmt.Println(x) // prints 100 (changed!)
Now the function directly modifies the original value.
Pointers to Structs
Pointers are very common when working with structs in Go.
Example:
type Person struct {
Name string
Age int
}
func birthday(p *Person) {
p.Age += 1
}
Usage:
p := Person{Name: "Alice", Age: 30}
birthday(&p)
fmt.Println(p.Age) // prints 31
Even more interesting: when you have a pointer to a struct, Go automatically dereferences it for you when accessing fields:
var p = &Person{Name: "Bob", Age: 25}
fmt.Println(p.Name) // Go reads (*p).Name automatically
Zero Value of a Pointer
When you declare a pointer without initializing it, its zero value is nil
.
var p *int
fmt.Println(p) // prints <nil>
Trying to dereference a nil
pointer causes a runtime panic. Always check or initialize before use!
Pointers vs Slices, Maps, Channels
In Go:
-
Slices, maps, and channels are reference types by design.
-
You don't need to use pointers to pass them around — they already behave like pointers!
func addElement(s []int) {
s[0] = 99
}
arr := []int{1, 2, 3}
addElement(arr)
fmt.Println(arr) // [99 2 3]
No explicit *
or &
needed here!
Common Mistakes with Pointers
-
Dereferencing a nil pointer → runtime panic.
-
Forgetting to use
&
when passing to a function expecting a pointer. -
Overusing pointers for small data types (e.g., int, bool) — sometimes passing by value is simpler and better!
A Quick Real-Life Analogy
Imagine variables as houses and pointers as house addresses:
-
A variable (
x
) is like your friend's house. -
A pointer (
p
) is a piece of paper with their house address. -
Dereferencing (
*p
) is you visiting the house to see (or modify) what's inside.
Final Words
Pointers may seem intimidating at first, but in Go, they are:
-
Simple,
-
Predictable,
-
Powerful.
Mastering pointers will help you write faster, more memory-efficient, and more idiomatic Go code.
Keep practicing, and pointers will become second nature!
📌 Quick Summary:
Concept | Symbol | Description |
---|---|---|
Get address | & |
p := &x |
Dereference | * |
value := *p |
Pointer to type | *T |
pointer to a value of type T |
Nil pointer | nil |
uninitialized pointer |