pointers in Go versus a value
Fast recall
Quick revision
Core answer
Compare pointers and a value using the same example, then give a clear selection rule.
Calling one option universally better without explaining the requirement.
Compare semantics and failure behaviour before discussing convenience or performance.
Interview-ready guide
Interview answer
Value parameters and receivers work on a copy and are ideal for small immutable-style data. Pointer forms share one value and support mutation, but they introduce nil handling and make ownership less local. They are related choices, but they do not promise the same behaviour.
For example: the function receives the address of
count, dereferences it, and changes the original value. Passingcountwithout&would give the function a copy instead. The alternative makes a different guarantee, so the code should reveal which guarantee the caller needs.Use a pointer when mutation must be visible to the caller, when copying a large struct would be wasteful, or when
nilhas a deliberate meaning such as 'not supplied'. Choose a value when its simpler or more explicit behaviour better matches the requirement.Use values for simple independent data; use pointers for intentional shared mutation, large values, or meaningful absence—and handle nil. Document or test the boundary when a future change could silently alter that decision.
pointers in Go versus a value
Direct Answer
Value parameters and receivers work on a copy and are ideal for small immutable-style data. Pointer forms share one value and support mutation, but they introduce nil handling and make ownership less local. Use values for simple independent data; use pointers for intentional shared mutation, large values, or meaningful absence—and handle nil.
Deep Dive & Architecture
For a nil-pointer panic, start at the dereference in the stack trace and move backward to the assignment or function return that produced nil.
Check constructor results, map lookups that return pointer values, optional request fields, interface values that may hold typed nil pointers, and concurrent mutation.
Value parameters and receivers work on a copy and are ideal for small immutable-style data. Pointer forms share one value and support mutation, but they introduce nil handling and make ownership less local. Use values for simple independent data; use pointers for intentional shared mutation, large values, or meaningful absence—and handle nil.
The common mistake is dereferencing a nil pointer or using a pointer when ordinary value semantics would be simpler. A nil pointer has no value behind it, so *p or p.Field can panic. Check optional pointers at boundaries, return useful errors with nil results, use value semantics by default for small data, and choose one receiver style consistently for a type.
Code Example
func renameValue(u User) { u.Name = "new" } // copy
func renamePointer(u *User) { u.Name = "new" } // original
Common Mistakes & Pitfalls
Calling one option universally better without explaining the requirement.
Check your understanding
Answer these without looking back at the article.
- What are pointers in Go, and how do they work?
- When should you use pointers in Go?
- What common mistakes should you avoid with pointers in Go?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.