Go supports pointers, allowing you to pass references to values and records within your program. Pointers are useful for large structs or when you need to modify a value in a function.
💡 Key Points
- Pointers store memory addresses of values
- Use
& to get a pointer to a variable - Use
* to dereference a pointer and access its value - Zero value of a pointer is
nil - Dereferencing a nil pointer causes a runtime panic
- Go does not support pointer arithmetic (unlike C/C++)
- Pointers enable functions to modify arguments
- Use pointers for large structs to avoid copying overhead
- Methods with pointer receivers can modify the receiver
- Struct field access through pointers is automatically dereferenced
Basic Pointer Operations
Pointers hold the memory address of a value. Use & to get a pointer and * to dereference:
package main
import "fmt"
func main() {
i := 42
// Get pointer to i with &
p := &i
fmt.Println("Value of i:", i)
fmt.Println("Address of i:", p)
fmt.Println("Value at pointer:", *p)
// Modify value through pointer
*p = 21
fmt.Println("New value of i:", i)
// Zero value of pointer is nil
var ptr *int
fmt.Println("Nil pointer:", ptr)
}
Output:Value of i: 42
Address of i: 0xc000012028
Value at pointer: 42
New value of i: 21
Nil pointer: <nil>
Pointers in Functions
Pass pointers to functions to allow them to modify the original value:
package main
import "fmt"
// Function with value parameter (copy)
func zeroValue(val int) {
val = 0
}
// Function with pointer parameter (reference)
func zeroPointer(ptr *int) {
*ptr = 0
}
func main() {
i := 1
fmt.Println("Initial:", i)
// Pass by value - doesn't modify original
zeroValue(i)
fmt.Println("After zeroValue:", i)
// Pass by reference - modifies original
zeroPointer(&i)
fmt.Println("After zeroPointer:", i)
}
Output:Initial: 1
After zeroValue: 1
After zeroPointer: 0
Pointer Syntax
| Operator | Syntax | Description | Example |
| Address-of | & | Get pointer to a variable | p := &x |
| Dereference | * | Access value at pointer | val := *p |
| Type Declaration | *T | Declare pointer to type T | var p *int |
| Nil Check | p == nil | Check if pointer is nil | if p != nil { } |
| New Function | new(T) | Allocate memory, return pointer | p := new(int) |
Pointer Characteristics
| Feature | Description | Notes |
| Zero Value | Nil for all pointer types | Dereferencing nil causes panic |
| Memory Address | Pointers store memory addresses | Typically displayed in hexadecimal |
| Type Safety | Pointers are typed | *int different from *string |
| No Arithmetic | Go doesn't support pointer arithmetic | Unlike C/C++, can't do ptr++ |
| Automatic Deref | Struct field access auto-dereferences | p.field instead of (*p).field |
| Pass by Value | Go passes everything by value | Pointers let you "pass by reference" |
Common Pointer Patterns
| Pattern | Code | Use Case |
| Modify in Function | func update(p *int) { *p = 10 } | Change original value in function |
| Struct Pointer | func (p *Person) SetAge(age int) | Method that modifies receiver |
| Optional Value | var config *Config | Nil indicates absence of value |
| Large Struct | func process(data *LargeData) | Avoid copying large structures |
| Linked Structures | type Node struct { Next *Node } | Build linked lists, trees, graphs |
| Factory Function | func NewPerson() *Person | Return pointer to new struct |
Pointers vs Values
| Aspect | Value | Pointer |
| Memory | Copies entire value | Copies memory address only |
| Modification | Cannot modify original | Can modify original value |
| Nil Check | Not applicable | Must check for nil |
| Performance | Fast for small types | Better for large structs |
| Semantics | Copy/independent value | Shared/referenced value |
| Safety | Always safe to use | Risk of nil pointer panic |