未知属性的接口

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

Interface with unknown properties

问题

我正在尝试使用frontmatter包中的Unmarshal方法来解析Markdown文件中的前置内容。

该函数的类型签名如下:

func Unmarshal(data []byte, v interface{}) (err error)

我已经获取了字节数据,并且我理解我需要将一个具有适当字段的接口/结构体作为第二个参数传递进去,但是我不知道我要解析的文件中的字段将是什么,而且重要的是我不要丢失数据。

该包在内部使用了yaml.v2,它提供了在解组之前定义接口的更全面的示例。

type T struct {
    A string
    B struct {
        RenamedC int   `yaml:"c"`
        D        []int `yaml:",flow"`
    }
}

然后创建结构体t的实例,并将指向t的指针传递给Unmarshal

t := T{}

err := yaml.Unmarshal([]byte(data), &t)

据我了解,只有当YAML文件看起来像这样时,这段代码才能正常工作:

a: Easy!
b:
  c: 2
  d: [3, 4]

第二个示例看起来更接近我所需要的。它似乎使用了一个map[interface{}]interface{}

m := make(map[interface{}]interface{})

err = yaml.Unmarshal([]byte(data), &m)

我对Go相对较新,对我来说,这看起来像一个通用的map,对于读取未知值来说是理想的。

我根据自己的项目改编了这个示例,并得到了以下代码。

m := make(map[interface{}]interface{})
err := frontmatter.Unmarshal(data, &m)

但是这导致了一个运行时错误

> panic: reflect: NumField of non-struct type

完整的堆栈跟踪在这里


我是否朝着正确的方向前进?如果是的话,出了什么问题?

英文:

I'm trying to use the Unmarshal method from the frontmatter package to parse front matter from a markdown file.

The type signature for the function is as follows

func Unmarshal(data []byte, v interface{}) (err error)

I've got the byte data and I understand that I need to pass an interface/struct with the appropriate fields as the second argument—however I don't know what the fields are going to be in the files that I parse and it's important that I don't lose data.

Internally this package uses yaml.v2 which provides a more comprehensive example for defining the interface before unmarshaling.

type T struct {
    A string
    B struct {
        RenamedC int   `yaml:"c"`
        D        []int `yaml:",flow"`
    }
}

Then create an instance of the struct t and pass a pointer to t through to Unmarshal.

t := T{}

err := yaml.Unmarshal([]byte(data), &t)

As I understand, this is only going to work if the YAML looks like this:

a: Easy!
b:
  c: 2
  d: [3, 4]

The second example looks closer to what I need. Rather than creating a struct, it seems to use a map of interface{} -> interface{}.

m := make(map[interface{}]interface{})

err = yaml.Unmarshal([]byte(data), &m)

I'm relatively new to Go and to me this looks like a generic map, which would be ideal for reading in unknown values.

I've adapted the example for my own project and ended up with the following code.

m := make(map[interface{}]interface{})
err := frontmatter.Unmarshal(data, &m)

But this results in a runtime error

> panic: reflect: NumField of non-struct type

Full stacktrace here.


Am I heading in the right direction? If so, what's going wrong?

答案1

得分: 0

原来,原始的yaml.Unmarshal方法足够强大,即使在提供整个文件的情况下,也只会提取出前置元数据。

我最终使用的解决方案如下所示:

// 读取由前置元数据和内容组成的文件
data, err := ioutil.ReadFile(file)

if err != nil {
  log.Fatal(err)
}

meta := make(map[interface{}]interface{})
yaml.Unmarshal([]byte(data), &meta)

这意味着不再需要使用frontmatter包,而是直接使用yaml包。

英文:

Turns out that the raw yaml.Unmarshal method is robust enough to only pick up the front matter, even when presented with the entire file.

The solution I ended up using looks like this.

// read file made up of front matter and content
data, err := ioutil.ReadFile(file)

if err != nil {
  log.Fatal(err)
}

meta := make(map[interface{}]interface{})
yaml.Unmarshal([]byte(data), &meta)

This means dropping the frontmatter package and using the yaml package directly.

huangapple
  • 本文由 发表于 2016年2月12日 21:05:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/35363398.html
匿名

发表评论

匿名网友

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

确定