自定义 UnmarshalYAML,如何在自定义类型上实现 Unmarshaler 接口

Posted

技术标签:

【中文标题】自定义 UnmarshalYAML,如何在自定义类型上实现 Unmarshaler 接口【英文标题】:Custom UnmarshalYAML, how to implement Unmarshaler interface on custom type 【发布时间】:2018-09-06 21:30:22 【问题描述】:

我解析一个 .yaml 文件,需要以自定义方式解组其中一个属性。我正在使用"gopkg.in/yaml.v2" 包。

有问题的属性是这样存储在我的 .yaml 文件中的:

endPointNumberSequences:
  AD1: [ 0, 10, 14, 1, 11, 2, 100, 101, 12 ]

所以它基本上是一种map[string][]uint16 类型。 但我需要map[string]EpnSeq,其中EpnSeq 定义为:type EpnSeq map[uint16]uint16

我的结构:

type CitConfig struct 
    // lots of other properties
    // ...

    EndPointNumberSequences  map[string]EpnSeq `yaml:"endPointNumberSequences"`

我尝试在其上实现 Unmarshaler 接口,如下所示:

// Implements the Unmarshaler interface of the yaml pkg.
func (e EpnSeq) UnmarshalYAML(unmarshal func(interface) error) error 
    yamlEpnSequence := make([]uint16, 0)
    err := unmarshal(&yamlEpnSequence)
    if err != nil 
        return err
    

    for priority, epn := range yamlEpnSequence 
        e[epn] = uint16(priority) // crashes with nil pointer
    

    return nil

我的问题是 UnmarshalYAML 函数内部没有定义 EpnSeq 类型,导致运行时出现 nil 指针异常。 如何在此处正确实现 Unmarshaler 接口?

【问题讨论】:

makeEpnSeq 在写入之前?例如。 *e = make(EpnSeq, len(yamlEpnSequence))。无论如何都需要一个指针接收器。 哇,我只是傻了。我试过这个,但在使用 make() 分配之前,我没有先取消引用指针。这样,指针仅在本地更改...我的错,对不起 @Volker:写一个答案,让自己获得一些互联网积分,哇哦 ;) 【参考方案1】:

由于@Volker 没有发表他的评论作为答案,为了完整起见,我会这样做。 所以我已经走在正确的道路上,但是在初始化它时根本没有取消引用我的结构的指针接收器:

// Implements the Unmarshaler interface of the yaml pkg.
func (e *EpnSeq) UnmarshalYAML(unmarshal func(interface) error) error 
    yamlEpnSequence := make([]uint16, 0)
    err := unmarshal(&yamlEpnSequence)
    if err != nil 
        return err
    

    // make sure to dereference before assignment, 
    // otherwise only the local variable will be overwritten
    // and not the value the pointer actually points to
    *e = make(EpnSeq, len(yamlEpnSequence))
    for priority, epn := range yamlEpnSequence 
        e[epn] = uint16(priority) // no crash anymore
    

    return nil

【讨论】:

以上是关于自定义 UnmarshalYAML,如何在自定义类型上实现 Unmarshaler 接口的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义类中调用“SetDlgItemText”?

如何在自定义视图类中使用 soundPool? [关闭]

如何在自定义对话框类中使用 getActivity.getLayoutInflater()

iOS - 如何在自定义单元格中使用继承?

如何在自定义视图类中链接 onSizeChanged()、onMeasure()、onDraw()

如何在自定义类中隐藏迭代器和容器实现(无增强)