GoYAML结构片

I am attempting to learn goyaml, and am having some issues with attempting to produce slices from yaml. I can marshal my struct into this example yaml, but I cannot unmarshal the same yaml back into the struct.

 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

struct:

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
}

When testing unmarshaling I'm getting reflect errors, as I understand it I think I may need to re-approach the design without struct slices, I was hoping someone could offer some insight into this?

errors:

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

The following code works just fine for me, outputting the original yaml text as it should:

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
}

Output:

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

(Of course you should not ignore errors in your actual code, like I'm doing here.)

EDIT:

Unmarshal needs a pointer to a struct in order to set its fields. If you call it with a plain struct value, it receives only a copy of the original struct (because in Go everything is passed as a copy), and therefore couldn't possibly alter the fields of the original struct.

Therefore, you have basically two options:

You can define and initialize c with c := &Configuration{}, i.e. defining it as a pointer to type Configuration while simultaneously pointing it to a new, zeroed Configuration value. Then you can call yaml.Unmarshal([]byte(yamlText), c).

Alternatively you can define c with var c Configuration, which means c is not a pointer, but a new zero value of type Configuration. In this case you need to explicitly pass a pointer to that value when you call Unmarshal: yaml.Unmarshal([]byte(yamlText), &c).

Note that the pointer you pass to Unmarshal must point to an existing Configuration value. var c *Configuration would define c as a pointer, but passing it immediately to Unmarshal would lead to an panic, as it's value is nil; it doesn't point to an existing Configuration value.

Also, in my code above there was originally a little typo, which is now fixed (though the code still worked). I wrote both c := &Configuration{} and yaml.Unmarshal([]byte(yamlText), &c), so I actually passed Unmarshal a pointer to a pointer to a struct, which Unmarshal was able to handle without issues.