【问题标题】:GoYAML struct slicesGoYAML 结构切片
【发布时间】:2016-03-12 20:02:45
【问题描述】:

我正在尝试学习 goyaml,但在尝试从 yaml 生成切片时遇到了一些问题。我可以将我的结构编组到这个示例 yaml 中,但我不能将相同的 yaml 解组回结构中。

 input:
  file:
  - file: stdin
  webservice:
  - port: "0000"
    address: 0.0.0.0
processing:
  regex:
  - regex: ^(this)*
    mapping: (1) thing
output:
  file:
  - file: stdout
  webservice:
  - port: "0000"
    address: 0.0.0.0

结构:

type Configuration struct{
    Input ioInstance
    Processing ProcessingInstance
    Output ioInstance
}

type ioInstance struct {
    File []FileInstance
    Webservice []WebserviceInstance
}

type FileInstance struct {
    File string
}

type WebserviceInstance struct  {
    Port string
    Address string
}

type ProcessingInstance struct {
    Regex []RegexInstance
}

type RegexInstance struct {
    Regex string
    Mapping string
}

在测试解组时,我遇到了反射错误,据我了解,我认为我可能需要在没有结构切片的情况下重新设计,我希望有人可以对此提供一些见解?

错误:

panic: reflect: reflect.Value.Set using unaddressable value [recovered]
    panic: reflect: reflect.Value.Set using unaddressable value [recovered]
    panic: reflect: reflect.Value.Set using unaddressable value

【问题讨论】:

  • 您使用的是最新的软件包吗? “github.com/go-yaml/yaml”已移至“gopkg.in/yaml.v2”

标签: go yaml slice


【解决方案1】:

以下代码对我来说效果很好,可以输出原始的 yaml 文本:

package main

import "fmt"
import "gopkg.in/yaml.v2"

func main() {
    c := &Configuration{}
    yaml.Unmarshal([]byte(yamlText), c) 
    buf, _ := yaml.Marshal(c)
    fmt.Println(string(buf))
}

var yamlText = ` 
input:
  file:
  - file: stdin
  webservice:
  - port: "0000"
    address: 0.0.0.0
processing:
  regex:
  - regex: ^(this)*
    mapping: (1) thing
output:
  file:
  - file: stdout
  webservice:
  - port: "0000"
    address: 0.0.0.0
`

type Configuration struct {
    Input      ioInstance
    Processing ProcessingInstance
    Output     ioInstance
}

type ioInstance struct {
    File       []FileInstance
    Webservice []WebserviceInstance
}

type FileInstance struct {
    File string
}

type WebserviceInstance struct {
    Port    string
    Address string
}

type ProcessingInstance struct {
    Regex []RegexInstance
}

type RegexInstance struct {
    Regex   string
    Mapping string
}

输出:

input:
  file:
  - file: stdin
  webservice:
  - port: "0000"
    address: 0.0.0.0
processing:
  regex:
  - regex: ^(this)*
    mapping: (1) thing
output:
  file:
  - file: stdout
  webservice:
  - port: "0000"
    address: 0.0.0.0

(当然,您应该忽略实际代码中的错误,就像我在这里所做的那样。)

编辑:

Unmarshal 需要一个指向结构的 指针 才能设置其字段。如果你用一个普通的结构值调用它,它只接收原始结构的 copy (因为在 Go 中 everything 作为副本传递),因此不能可能会更改原始结构的字段。

因此,您基本上有两种选择:

您可以使用c := &Configuration{} 定义和初始化c,即将其定义为指向Configuration 类型的指针,同时将其指向一个新的、归零的Configuration 值。然后你可以拨打yaml.Unmarshal([]byte(yamlText), c)

或者,您可以用var c Configuration 定义c,这意味着c 不是指针,而是Configuration 类型的新零值。在这种情况下,您需要在调用 Unmarshal 时显式传递指向该值的指针:yaml.Unmarshal([]byte(yamlText), &c)

请注意,您传递给 Unmarshal 的指针必须指向 现有 Configuration 值。 var c *Configuration 会将c 定义为一个指针,但是将它立即传递给Unmarshal 会导致恐慌,因为它的值是nil;它不指向现有的 Configuration 值。

另外,在我上面的代码中,最初有一个小错字,现在已修复(尽管代码仍然有效)。我写了c := &Configuration{}yaml.Unmarshal([]byte(yamlText), &c),所以我实际上传递了Unmarshal 一个指向结构指针的指针Unmarshal 能够毫无问题地处理它。

【讨论】:

  • 这成功了!谢谢,我之前使用var config Configuration 来初始化你能解释一下为什么这有效而这无效吗?
  • @TimTanasse,我在答案中添加了解释。
  • 非常感谢!看来我有点太习惯Java了
猜你喜欢
  • 2015-02-21
  • 2014-08-24
  • 2020-11-24
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多