2

Is there any way to set an interface field using reflect? When i tried to set it, it paniced saying that the value is non addressable.

type A interface{...}

func CreateA(name string) A {...}

type B struct {
   field A
   should A
   mirror A
}

// normal way of initializing
var b = B{
  field: CreateA("field"),
  should: CreateA("should"),
  mirror: CreateA("mirror"),
}

func MirrorField(b *B) {
   t := reflect.TypeOf(b)
   v := reflect.ValueOf(b)
   for i := 0; i < t.NumField(); i++ {
      setTo = CreateA(t.Field(1).Name)
      fieldVal := v.Field(i)
      fieldVal.Set(reflect.ValueOf(setTo))
   }
}

// what i want is something like
var b = &B{}
MirrorField(b)
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Ary Purnomoz
  • 131
  • 2
  • 9
  • 1
    What would you reflect on? The above code compiles fine. What problem do you have? – Rob Napier Feb 18 '15 at 20:13
  • 1
    One normally uses a [type assertion](http://golang.org/ref/spec#Type_assertions) for this. What are you trying to do with reflection? – JimB Feb 18 '15 at 23:01

1 Answers1

2

Interfaces don't have fields, they only define a method set of the value they contain. When reflecting on an interface, you can extract the value with Value.Elem().

You also can't Set unexported fields. You need to capitalize the field names in your B type. When iterating over the fields, use Value.CanSet() to test if they are settable. CanSet() will also return false is the value isn't addressable, or the value is still in an interface.

A working example of your code: http://play.golang.org/p/Mf1HENRSny

JimB
  • 104,193
  • 13
  • 262
  • 255
  • so there is no way to set a field with interface as the type? – Ary Purnomoz Feb 19 '15 at 18:33
  • Sure you can. It doesn't matter what the type of the field is as long as it's a valid assignment. Your original question doesn't make sense, and may be the source of your confusion, because there's no such thing as an "interface field". Interfaces only define a method set. You need the value contained in the interface, which you can get via `Elem()` (or `reflect.Indirect()`). – JimB Feb 19 '15 at 18:51