You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:12:26