A pointer is a value that holds the memory address of another value. The & operator takes the address of a variable, producing a pointer; the * operator, applied to a pointer, dereferences it to get (or set) the value it points to. Unlike C, Go does not allow arithmetic on pointers (no ptr++), which removes an entire class of memory-corruption bugs while keeping the ability to share and mutate data across function calls.
& and *: address-of and dereference
&x produces a pointer to x, of type *T if x is type T. Given a pointer, *p reads or writes the value it points to.
x := 10
p := &x // p is a *int, holding x's address
fmt.Println(*p) // 10 — dereference to read the value
*p = 20 // dereference to write — this changes x too
fmt.Println(x) // 20Why pass a pointer to a function
Go passes arguments by value — a function normally receives a copy. Passing a pointer instead lets a function mutate the caller's original data, and avoids copying large structs on every call.
func double(n int) { // receives a COPY
n *= 2
}
func doublePtr(n *int) { // receives the ADDRESS
*n *= 2
}
x := 5
double(x)
fmt.Println(x) // still 5 — double() only changed its copy
doublePtr(&x)
fmt.Println(x) // 10 — doublePtr() changed the originalNo pointer arithmetic, and nil pointers
C lets you increment a pointer to walk through memory (ptr++); Go does not allow this at all — it's a compile error. This single restriction eliminates buffer overruns and a large share of classic C memory bugs. A pointer's zero value is nil, meaning it points to nothing; dereferencing a nil pointer (*p when p == nil) causes a runtime panic, so code that receives a pointer typically checks for nil before dereferencing it.