Explain the laws of reflection and settability. What does this print?
type Config struct {
Port int
host string
}
c := Config{Port: 80}
v := reflect.ValueOf(c)
fmt.Println(v.Field(0).CanSet())
p := reflect.ValueOf(&c).Elem()
fmt.Println(p.Field(0).CanSet(), p.Field(1).CanSet())
p.Field(0).SetInt(8080)
fmt.Println(c.Port, p.Kind(), reflect.TypeOf(&c).Kind())
Output:
false
true false
8080 struct ptr
Laws: (1) reflection goes from interface value to reflection object (TypeOf/ValueOf); (2) back via v.Interface(); (3) to modify a Value it must be settable — addressable and not obtained through unexported fields. ValueOf(c) holds a copy, so nothing is settable; you need ValueOf(&c).Elem(). Unexported fields can be read (v.Field(1).String()) but not set or Interface()d.
Kind vs Type: Kind is the underlying category (struct, ptr, slice); Type is the named type (main.Config). Calling SetInt on a non-int Kind or non-settable value panics — reflection moves type errors from compile time to runtime. Interviewers like hearing: reflection is slow (allocations, no inlining), so prefer generics or code generation where possible; stdlib uses it for encoding/json, fmt, text/template.
More on Standard Library, HTTP & Systems Design in Go
- Q464time.Ticker, time.After and timers: what leaks, and what changed in Go 1.23?
- Q465What does this print? (time.Duration arithmetic gotchas)
- Q467Use reflection to build a simple struct-tag validator (`validate:"required,max=10"`).
- Q468Design a per-client rate limiter for an HTTP API. Implement a token bucket.
- Q469Design a concurrency-safe, generic LRU cache with TTL.
- Q470What is a cache stampede and how does singleflight solve it?