Go

Can you modify a struct stored inside an interface? What does this print?

Question 108HardGo 1.22 to 1.25
type P struct{ X int }

func main() {
    var i any = P{1}
    // i.(P).X = 2   // compile error: cannot assign to i.(P).X
    //               // (neither addressable nor a map index expression)

    p := i.(P)       // p is a copy
    p.X = 2
    fmt.Println(i)   // ?

    var j any = &P{1}
    j.(*P).X = 2     // OK: modifies the pointee
    fmt.Println(j.(*P).X) // ?
}

Output:

{1}
2

Assigning P{1} to i copies the struct into storage the interface owns. The result of a type assertion is a fresh, non-addressable value, so you cannot assign through it, and the local variable p is a second copy. The runtime also relies on this: several interface values may share one boxed copy, so in-place mutation would be unsafe.

To mutate, either store a pointer in the interface (any(&P{})), or read, modify and write back (p := i.(P); p.X = 2; i = p). The same rule is why a pointer-receiver method cannot be called on a value held in an interface, and why reflect.ValueOf(i).Field(0).SetInt(2) panics with "unaddressable value" when i holds a struct rather than a pointer.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions