- Key points about Pointers in golang
- Pointer is an address (of a variable)
&
means address-of*
means two things:- (part of a type)
*int
means a pointer type with anint
base type - (unary operator)
*myVar
means value-at, meaning dereferencemyVar
*nil
creates apanic
(dereferencing a nil pointer)
- (part of a type)
- all stack frames are independent/isolated (cannot access other stack frames)
- C++ has both References and Pointers (the difference)
- C++ discourages pointers
- Passing pointer is not always faster since golang needs to do escape analysis to decide where to allocate (stack or heap)
- function parameters pass by value (copy)
- compiler will copy arguments from caller stack frame to callee stack frame
- If the value is a pointer, callee can mutate value (at the address)
- Passing pointer trades immutability for less copying
- If func accepts interface ...
- (convenience) Caller can pass value if no receivers accept pointer (because passing address makes no difference)
- Otherwise, caller must pass address of the implementation
- Compiler & IDE enforces all of this
- Maps, slices, channels, pointers, functions pass "like" references
- They are passing address
by-value
- They are passing address
- returned parameters pass by value (copy)
- compiler will copy return values from callee stack frame to caller stack frame
- If the return value is a pointer, compiler will allocate on heap
func acceptValue(p int) {
// changes have zero impact on caller
p = 10
}
func acceptPointer(p *int) {
// mutate value at p, affects caller
*p = 10
// CANNOT make caller's pointers point somewhere else
}
- Accept pointer for mutation & REALLY large objects
- Accept non-pointer for immutability