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

Golang中结构体内部类型别名YAML反序列化失败问题排查

问题:YAML反序列化后Kind字段值未正确更新

问题场景

需要将以下YAML内容反序列化到Resource结构体:

kind: bar
name: baryaml

Resource及相关类型定义如下:

type Kind int

const (
    KIND_FOO Kind = iota
    KIND_BAR
)

type Resource struct {
    Kind Kind
    Name string
}

已实现Kind类型的UnmarshalYAML方法,控制台输出显示已解析出正确的Kind值(1),但最终Resource实例的Kind字段仍为初始值0,与预期不符:

当前输出:

# Output:
Unmarshaled kind: 1
yamlBar: {0 baryaml}

预期输出:

# Expected Output:
Unmarshaled kind: 1
yamlBar: {1 baryaml}

相关完整代码:

package main

import (
    "fmt"

    "gopkg.in/yaml.v3"
)

type Kind int

const (
    KIND_FOO Kind = iota
    KIND_BAR
)

func (k *Kind) UnmarshalYAML(value *yaml.Node) error {
    var kind string
    err := value.Decode(&kind)

    if err != nil {
        return err
    }

    var x Kind

    switch kind {
    case "foo":
        x = KIND_FOO
    case "bar":
        x = KIND_BAR
    default:
        return fmt.Errorf("unknown kind: %s", kind)
    }

    k = &x
    fmt.Println("Unmarshaled kind:", *k)
    return nil
}

type Resource struct {
    Kind Kind
    Name string
}

func main() {

    var yamlBar = `
kind: bar
name: baryaml
`
    r := Resource{}
    err := yaml.Unmarshal([]byte(yamlBar), &r)

    if err != nil {
        panic(err)
    }

    fmt.Println("yamlBar:", r)
}

问题原因

问题出在UnmarshalYAML方法中的k = &x这行代码。

在Go语言中,指针类型的方法接收者是值传递的——方法内部的k是原接收者指针的副本。当你执行k = &x时,只是修改了这个副本的指向,让它指向局部变量x的地址,但完全没有修改原Resource结构体中Kind字段的内存值。原结构体的Kind字段始终是初始值0,自然不会被更新。

修复方法

不要重新给接收者指针赋值,而是直接修改指针指向的内存内容,将k = &x替换为*k = x:

修改后的UnmarshalYAML方法:

func (k *Kind) UnmarshalYAML(value *yaml.Node) error {
    var kind string
    err := value.Decode(&kind)

    if err != nil {
        return err
    }

    var x Kind

    switch kind {
    case "foo":
        x = KIND_FOO
    case "bar":
        x = KIND_BAR
    default:
        return fmt.Errorf("unknown kind: %s", kind)
    }

    *k = x // 直接修改指针指向的内存值
    fmt.Println("Unmarshaled kind:", *k)
    return nil
}

这样修改后,解析得到的x值会直接写入到Resource结构体Kind字段的内存地址中,最终就能得到符合预期的结果。

内容的提问来源于stack exchange,提问作者C. Falsaperla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:30:59