如何在Golang中从YAML中解析结构体中的类型别名?

huangapple go评论116阅读模式
英文:

How to unmarshal type aliases inside structs from yaml in golang?

问题

我想要以下的yaml内容:

kind: bar
name: baryaml

被解析到结构体Resource中:

type Kind int

const (
    KIND_FOO Kind = iota
    KIND_BAR
)

type Resource struct {
    Kind Kind
    Name string
}

有人能解释一下为什么下面的代码无法正确存储kind,即使它被正确解析了吗?

# 输出:
Unmarshaled kind: 1
yamlBar: {0 baryaml}
# 期望输出:
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)
}
英文:

I would like the following yaml

kind: bar
name: baryaml

to be unmarshaled inside the struct Resource

type Kind int

const (
    KIND_FOO Kind = iota
    KIND_BAR
)

type Resource struct {
    Kind Kind
    Name string
}

Could someone explain why the code below is unable to store the correct kind, even though it is being unmarshaled correctly?

# 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)
}

答案1

得分: 0

感谢@JimB建议解引用k指针:

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

    if err != nil {
        return err
    }

    switch kind {
    case "foo":
        *k = KIND_FOO
    case "bar":
        *k = KIND_BAR
    default:
        return fmt.Errorf("未知的类型: %s", kind)
    }

    fmt.Println("解组的类型:", *k)
    return nil
}
英文:

Thanks to @JimB for suggesting to dereference the k pointer:

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

	if err != nil {
		return err
	}

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

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

huangapple
  • 本文由 发表于 2023年1月28日 02:26:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75262000.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定