I've been struggling with the reflect package. This code below does what I expect:
package main
import (
"reflect"
"log"
)
type Car struct {
Model string
}
type Person struct {
Name string
Cars []Car
}
func ModifyIt(parent interface{},fieldName string, val interface{}) {
slice := reflect.ValueOf(parent).Elem()
nth := slice.Index(0)
//row := nth.Interface() // this line causes errors
row := nth.Interface().(Person)
elem := reflect.ValueOf(&row).Elem()
field := elem.FieldByName(fieldName)
log.Println(field.CanSet())
}
func main() {
p := []Person{Person{Name:"john"}}
c := []Car{Car{"corolla"},Car{"jetta"}}
ModifyIt(&p,"Cars",&c)
}
However, if I replace the line row := nth.Interface().(Person)
with row := nth.Interface()
, that is I remove the type assertion, then I get the error:
panic: reflect: call of reflect.Value.FieldByName on interface Value on line "field := elem.FieldByName(fieldName)
I've tried a bunch of other things the last few hours like trying to do reflect.TypeOf()
, reflect.Indirect()
etc... on some of the other variables but with no success.
I've read some other questions like these:
reflect: call of reflect.Value.FieldByName on ptr Value
Set a struct field with field type of a interface
Golang reflection: Can't set fields of interface wrapping a struct
They seem to suggest that I don't have a good understanding of how pointers or interfaces work.
So my question is, how do I go about setting the field of a struct when the struct is typed as an interface?
UPDATE
I posted a solution as an answer, but I have no confidence in whether it is the proper or safe way of doing things. I hope someone can explain, or post a better solution.