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())
}
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.