I try to write a function to update all string fields of arbitrary structs, like this:
type Student struct {
Name string
Age int
}
func SetStringField(obj interface{}) {
reflect.ValueOf(obj).Elem().FieldByName("Name").SetString("set name")
}
func main() {
student := Student{
"alice",
12,
}
SetStringField(&student)
}
but this func can only update specific field. And I try this:
func SetStringField2(obj interface{}) {
// Keys := reflect.TypeOf(obj)
Values := reflect.ValueOf(obj)
count := reflect.ValueOf(obj).NumField()
for i := 0; i < count; i++ {
// fieldKey := Keys.Field(i).Name
fieldValue := Values.Field(i)
switch fieldValue.Kind() {
case reflect.String:
// fieldValue.CanSet()==false
fieldValue.SetString("fieldCleanString2 set name")
// panic: reflect: call of reflect.Value.FieldByName on interface Value
// reflect.ValueOf(&obj).Elem().FieldByName(fieldKey).SetString("123")
}
}
}
func main() {
student := Student{
"alice",
12,
}
SetStringField2(student)
}
And calling SetStringField2(&student) got "panic: reflect: call of reflect.Value.NumField on ptr Value"
So, are there any other methods to do this work?
The problem is that the reflect value is not settable. To fix this issue, create the reflect value from a pointer.
// SetStringField2 sets strings fields on the struct pointed to by ps.
func SetStringField2(ps interface{}) {
v := reflect.ValueOf(ps).Elem() // Elem() dereferences pointer
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
switch fv.Kind() {
case reflect.String:
fv.SetString("fieldCleanString2 set name")
}
}
}
Pass a pointer to the value to the function:
student := Student{
"alice",
12,
}
SetStringField2(&student)