Quick Fix: The 30-Second Solution
To stop this panic, you must pass a pointer to your variable and call .Elem(). Go cannot modify a value passed by copy because the reflection object doesn't own the original memory address.
// ❌ Fails: Passing a copy (unaddressable)
val := reflect.ValueOf(myVar)
val.Set(reflect.ValueOf(newValue))
// ✅ Works: Passing a pointer and dereferencing
val := reflect.ValueOf(&myVar).Elem()
val.Set(reflect.ValueOf(newValue))
Why is this happening?
You’ll run into this 'unaddressable value' error whenever you try to modify a variable through reflection without giving Go its memory address. Usually, this happens when a variable is passed to reflect.ValueOf() by value instead of by reference.
panic: reflect: reflect.Value.Set using unaddressable value
goroutine 1 [running]:
reflect.Value.Set(...)
/usr/local/go/src/reflect/value.go:2235
main.main()
/path/to/your/code.go:15
The Root Cause: Addressability vs. Settability
Go's reflection package protects you from silent bugs. When you call reflect.ValueOf(x), Go creates a reflection object containing a copy of x. If the runtime allowed you to call Set() on this copy, you’d successfully update a temporary variable while the original remained untouched. To prevent this confusing behavior, Go triggers a panic.
Technically, a reflect.Value is only settable if it meets two criteria:
- It is **addressable** (it holds the actual memory address of the original data).
- It is not an **unexported** struct field (private fields remain read-only).
Step-by-Step Solutions
1. The Pointer + Elem Pattern
Pass the address of the variable (&name) so the reflection package knows exactly where the data lives. Note that simply passing a pointer isn't enough; reflect.ValueOf(&name) represents the pointer itself. You can't force-feed a string into a pointer type. Instead, use .Elem() to reach the actual value the pointer is guarding.
func main() {
name := "Initial State"
// 1. Get Value of the pointer
ptr := reflect.ValueOf(&name)
// 2. Dereference to get the actual string
v := ptr.Elem()
if v.CanSet() {
v.SetString("Updated State")
}
fmt.Println(name) // Output: Updated State
}
2. Modifying Struct Fields
Structs follow the same rules. If you pass a struct by value, every field inside that reflection object becomes unaddressable. To update a specific field, you must start with a pointer to the struct.
type Config struct {
Retries int
}
c := Config{Retries: 3}
// ✅ Always use the pointer to the struct
rv := reflect.ValueOf(&c).Elem()
field := rv.FieldByName("Retries")
if field.CanSet() {
field.SetInt(5)
}
Production Safety: Always Verify
In production code, avoid assuming your inputs are correct. Checking CanSet() adds less than 10 nanoseconds of overhead—a tiny price to pay to prevent an entire application crash if a non-pointer is passed by mistake.
func SafeUpdate(target interface{}, data interface{}) {
v := reflect.ValueOf(target)
// Ensure we are dealing with a pointer
if v.Kind() != reflect.Ptr {
return
}
elem := v.Elem()
if elem.CanSet() {
elem.Set(reflect.ValueOf(data))
}
}
The Takeaway
- **Panic Cause:** Attempting to use `Set()` on a reflection value created from a copy.
- **The Fix:** Pass the memory address (`&variable`) and call `.Elem()`.
- **Pro-Tip:** Always check `v.CanSet()` before performing a modification to keep your code robust.

