Go语言动态修改Struct的YAML标签后yaml.Unmarshal指针报错求解
解决动态修改Struct标签后YAML解码的指针问题
问题根源
你判断的没错,node.Decode必须接收指针类型才能修改内部值,你当前创建的newValue是不可寻址的结构体值,导致解码时无法完成赋值操作。同时,解码完成后还需要把新类型的值同步回原User实例。
修正后的代码
package main import ( "fmt" "reflect" "gopkg.in/yaml.v3" ) type User struct { Name string `yaml:"dummy"` } func (u *User) UnmarshalYAML(node *yaml.Node) error { t := reflect.TypeOf(*u) fields := make([]reflect.StructField, 0, t.NumField()) // 遍历字段,修改指定标签 for i := 0; i < t.NumField(); i++ { field := t.Field(i) if field.Name == "Name" { field.Tag = `yaml:"name"` // 动态修改标签 } fields = append(fields, field) } // 创建新的结构体类型 newType := reflect.StructOf(fields) // 分配新类型的零值并获取指针(可寻址) newPtr := reflect.New(newType) // 解码到新类型指针 if err := node.Decode(newPtr.Interface()); err != nil { return err } // 将新类型的值转换回原User类型,赋值给原实例 *u = newPtr.Elem().Interface().(User) return nil } var dat string = `name: abc` func main() { out := User{} if err := yaml.Unmarshal([]byte(dat), &out); err != nil { panic(err) } fmt.Printf("%+v\n", out) // 输出:{Name:abc} }
关键修改点
- 使用
reflect.New(newType)创建新结构体类型的指针,该指针指向的内存是可寻址的,满足node.Decode的要求 - 解码完成后,通过
newPtr.Elem()获取指针指向的结构体值,再转换为原User类型,赋值给原实例*u,确保原对象能拿到解码后的数据
内容的提问来源于stack exchange,提问作者user2847598
相关产品推荐
相关产品推荐

