Search code examples
reflectiongogo-interface

set variable of any struct passed as interface{}


I would like to know how to set a variable using reflection when using an interface{} value, and all kind of structs could be passed to func F(o interface{}). How to change the first value (s.A) to 'hello'?

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    A string
}

func main() {
    F(T{"foo"})
}

func F(o interface{}) {

    t := reflect.ValueOf(&T{"bar"}).Elem()
    s := reflect.ValueOf(&o).Elem()

    // ok
    fmt.Println("struct:   ", t.Field(0).CanSet())

    // panics - how to set s.A?
    fmt.Println("interface:", s.Field(0).CanSet())
}

Solution

  • See http://play.golang.org/p/F6M5mfMOTY

    When you pass the reference value &o, to reflect.ValueOf, Go is interpreting the Elem() as interface{}, not your original type. If you don't pass as a reference, you get a (non-addressable) instance of your type. I am not 100% sure why this is, but you can definitely see the behavior at the play link above.

    One approach would be to create a new addressable instance of your type, and then iterate over the value returned by s to set the fields in the new instance and then return it.