Using reflect, iterate a pointer-to-struct's fields
Tests fluency with Go reflection for indirection and field traversal. Outline: ValueOf/TypeOf, guard IsValid, check Kind==Ptr, Elem to struct, loop NumField with Type for names and Value for values. Red flag: Field() on the pointer before Elem panics.
What's really being asked
This question probes whether you understand the dual nature of Go's reflect package: reflect.Type describes the schema while reflect.Value holds the actual data. It specifically checks if you know how to safely navigate pointer indirection, validate kinds before calling type-specific methods, and iterate struct fields without causing a runtime panic. Interviewers also listen for awareness of package-level constants like reflect.Ptr and reflect.Struct versus the more general category kinds.
The full answer
First, obtain both views by calling reflect.TypeOf and reflect.ValueOf on the input, and immediately guard against invalid or nil input using IsValid and optionally IsNil. Second, check that the Value's Kind equals reflect.Ptr; if so, call Elem to dereference it, then verify the resulting Kind equals reflect.Struct. Third, loop from zero to the struct Value's NumField minus one. Inside the loop, use the Type's Field method to get the StructField which carries the Name, and use the Value's Field method to get a Value representing the field's data. Fourth, safely print values by calling Interface on each field Value, but only after confirming CanInterface returns true, because Interface panics on unexported fields. Optionally mention that if you only need fmt.Printf formatting, you can skip Interface and use the Value directly, or that you could use a type switch for primitive kinds if you need custom formatting.
The mistakes people make
Calling NumField or Field directly on the original pointer Value instead of on the result of Elem; this always panics because a pointer has no fields. Using TypeOf on the dereferenced Value but forgetting to also call Elem on the Value side, leaving you with a pointer Value that cannot yield field data. Assuming all fields can be converted via Interface and getting a runtime panic on unexported fields. Conflating reflect.Ptr with reflect.Interface and attempting Elem on an interface type rather than the expected pointer. Another subtle mistake is ignoring IsNil on pointer Values, which can lead to panics when calling Elem on a nil pointer.
What usually comes next
How would you recursively handle nested structs or slices of structs? What if the requirement changes to modifying fields instead of printing them, and how does addressability affect Set? How does the performance of reflection compare to direct access or code generation? What is the difference between VisibleFields and the older FieldByIndex behavior? Can you use struct tags to filter or rename output, and how does Tag.Lookup work?
A concrete example
func Inspect(v any) { val := reflect.ValueOf(v); if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() { return } val = val.Elem(); if val.Kind() != reflect.Struct { return } typ := val.Type(); for i := 0; i < val.NumField(); i++ { fieldVal := val.Field(i); name := typ.Field(i).Name; if fieldVal.CanInterface() { fmt.Printf("%s: %v\n", name, fieldVal.Interface()) } else { fmt.Printf("%s: <unexported>\n", name) } } }
Interview question
When reflecting over a pointer-to-struct to print field names and values, which approach avoids runtime panics?
- a.Call reflect.ValueOf, guard with IsValid, check Kind == Ptr and IsNil, call Elem, check Kind == Struct, then loop NumField using Type for names and Value for values, calling Interface only if CanInterface is trueCorrect
- b.Call reflect.ValueOf, check Kind == Ptr and IsNil, call Elem, check Kind == Struct, then loop NumField using Type.Field for names and call Interface on every field Value
- c.Call reflect.ValueOf and TypeOf, call Elem only on the Type, then iterate NumField using Type for names and the original pointer Value for field data
- d.Call reflect.ValueOf, check Kind == Ptr, then call NumField and Field directly on the original Value, using Type.Field for names and Interface for values
Why? this is the answer
Option A correctly dereferences the pointer via Elem on the Value side, validates struct kind, and guards Interface with CanInterface to avoid panics on unexported fields. Option B is tempting because it properly handles pointer indirection but omits the CanInterface check, causing a panic when encountering unexported fields.
Just read this? Test yourself on what you have been reading.
Read the original → pkg.go.dev
- #go
- #reflection
- #structs
- #intermediate
- #pointer-indirection
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on go — each one lists the topics its interview covers.
See open roles