Я пишу код, который анализирует файл YAML и проверяет данные внутри. Каждый синтаксический анализатор возвращает ошибку, если найденное значение не соответствует требованиям. Прямо сейчас я создаю массив ошибок и устанавливаю возврат каждого вызова к другому индексу в массиве. Моя текущая реализация работает, но кажется неправильной, и я хочу посмотреть, есть ли лучший способ добиться этого.

Вот пример

func createStruct(yamlMap map[interface{}]interface{}) (myStruct, error) {
    errs := make([]error, 6)
    s := myStruct{}

    s.Name, errs[0] = getString(yamlMap, "name", true)
    s.Tag, errs[1] = getIntValidRange(yamlMap, "tag", 1, 4094, true)
    s.TaggedPorts, errs[2] = getStringPortList(yamlMap, "tagged_ports", true)
    s.UntaggedPorts, errs[3] = getStringPortList(yamlMap, "untagged_ports", true)
    s.IP, errs[4] = getIPString(yamlMap, "ip", true)
    s.Netmask, errs[5] = getIPString(yamlMap, "netmask", true)

    return s, structCreateErrorChecker(errs)
}

Причина, по которой я не обрабатываю каждую ошибку после каждой функции, заключается в том, что я хочу сначала все проанализировать, а затем собрать все ошибки и зарегистрировать их. Это то, что делает structCreateErrorChecker ().

Вот YAML, который я пытаюсь разобрать (он появляется в комментариях). Когда я говорю "динамический", я имею в виду, что может быть любое количество секций control_bridge, и каждая секция vlan может иметь любое количество vlan.

controlling_bridge_1:
    ip:    "1.1.1.1"
    ports: ["1","2"]
    vlans:
        vlan01:
            name:  "vlan1"
            tag:   1001
            ports: ["1"]
            ip:    "2.2.2.2"
        vlan02:
            name:  "vlan02"
            tag:   1002
            ports: ["3", "4"]
            ip:    "3.3.3.1"

controlling_bridge_2:
    ip:    "1.1.1.1"
    ports: ["1","2"]
    vlans:
        vlan01:
            name:  "vlan1"
            tag:   1001
            ports: ["1"]
            ip:    "2.2.2.2"
        vlan02:
            name:  "vlan02"
            tag:   1002
            ports: ["3", "4"]
            ip:    "3.3.3.1"
go
0
jhall1990 5 Окт 2018 в 16:55

1 ответ

Лучший ответ

Официальной библиотеки yaml нет, но gopkg.in/yaml.v2 - хороший выбор. Чтобы демаршалировать данный yaml, вы можете определить структуры и добавить теги yaml к атрибутам.

Используя карты для ваших мостов и vlan, а также массивы для портов, вы можете без проблем демаршалировать данные.

При использовании карт имейте в виду, что итерация по карте не гарантирует порядок возвращаемых элементов.

Эта программа демаршалирует вашу данную структуру:

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

var data = `
controlling_bridge_1:
    ip:    "1.1.1.1"
    ports: ["1","2"]
    vlans:
        vlan01:
            name:  "vlan1"
            tag:   1001
            ports: ["1"]
            ip:    "2.2.2.2"
        vlan02:
            name:  "vlan02"
            tag:   1002
            ports: ["3", "4"]
            ip:    "3.3.3.1"

controlling_bridge_2:
    ip:    "1.1.1.1"
    ports: ["1","2"]
    vlans:
        vlan01:
            name:  "vlan1"
            tag:   1001
            ports: ["1"]
            ip:    "2.2.2.2"
        vlan02:
            name:  "vlan02"
            tag:   1002
            ports: ["3", "4"]
            ip:    "3.3.3.1"
`

type Bridge struct {
    IP    string   `yaml:"ip"`
    Ports []string `yaml:"ports"`
    Vlans map[string]Vlan
}

type Vlan struct {
    Name  string   `yaml:"name"`
    Tag   string   `yaml:"tag"`
    Ports []string `yaml:"ports"`
    IP    string   `yaml:"ip"`
}

func main() {
    bridges := map[string]Bridge{}

    err := yaml.Unmarshal([]byte(data), &bridges)
    if err != nil {
        log.Fatalf("error: %v", err)
    }

    fmt.Printf("%+v\n", bridges)
}
2
mbuechmann 5 Окт 2018 в 18:31