猿问

如何更新任意go结构的所有字符串字段?

我尝试编写一个函数来更新任意结构的所有字符串字段,如下所示:


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)

}



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)

}

fieldValue.SetString() 得到“恐慌:反射:reflect.flag.mustBeAssignable 使用不可寻址的值”,因为 fieldValue.CanSet()==false。

Reflect.ValueOf(&obj).Elem().FieldByName(fieldKey).SetString("fieldCleanString2 set name") 也失败,得到“恐慌:反射:在接口 Value 上调用reflect.Value.FieldByName”。

调用 SetStringField2(&student) 得到“恐慌:反射:在 ptr Value 上调用reflect.Value.NumField”


那么,还有其他方法可以完成这项工作吗?



梵蒂冈之花
浏览 134回答 2
2回答

慕桂英4014372

问题是反射值不可设置。要解决此问题,请从指针创建反射值。// SetStringField2 sets strings fields on the struct pointed to by ps.func SetStringField2(ps interface{}) {&nbsp; &nbsp; v := reflect.ValueOf(ps).Elem() // Elem() dereferences pointer&nbsp; &nbsp; for i := 0; i < v.NumField(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; fv := v.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; switch fv.Kind() {&nbsp; &nbsp; &nbsp; &nbsp; case reflect.String:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fv.SetString("fieldCleanString2 set name")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}将指向值的指针传递给函数:student := Student{&nbsp; &nbsp; "alice",&nbsp; &nbsp; 12,}SetStringField2(&student)在操场上运行它。

三国纷争

解决方案一:package serviceimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "reflect"&nbsp; &nbsp; "testing")func SetStringField2(obj interface{}) {&nbsp; &nbsp; Values := reflect.ValueOf(obj).Elem()&nbsp; &nbsp; count := reflect.Indirect(reflect.ValueOf(obj)).NumField()&nbsp; &nbsp; for i := 0; i < count; i++ {&nbsp; &nbsp; &nbsp; &nbsp; fieldValue := Values.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; switch fieldValue.Kind() {&nbsp; &nbsp; &nbsp; &nbsp; case reflect.String:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fieldValue.SetString("fieldCleanString2 set name")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func TestSetValue(t *testing.T) {&nbsp; &nbsp; type Student struct {&nbsp; &nbsp; &nbsp; &nbsp; Name string&nbsp; &nbsp; &nbsp; &nbsp; Age&nbsp; int&nbsp; &nbsp; }&nbsp; &nbsp; student := &Student{&nbsp; &nbsp; &nbsp; &nbsp; "alice",&nbsp; &nbsp; &nbsp; &nbsp; 12,&nbsp; &nbsp; }&nbsp; &nbsp; SetStringField2(student)&nbsp; &nbsp; fmt.Print(student.Name)}
随时随地看视频慕课网APP

相关分类

Go
我要回答