Различайте «Без ключа» и «Без значений» при десериализации/отмене привязки списка Yaml к структуре Golang

# #go #yaml #config #unmarshalling

Вопрос:

Я удаляю файл конфигурации Yaml из структуры Golang. Я хочу реализовать следующую логику:

 if blacklist key is not there in yaml:
    then allow everything
else if blacklist key is there but there are no values:
    then block everything
else if blacklist values are there in yaml:
    then filter out only the listed items
 

Я не могу отличить два последних сценария.
По сути, оба выглядят одинаково, т. Е. «ключ черного списка не имеет значения», но мне интересно, возможен ли какой-либо способ. (без введения какого-либо дополнительного флага в yaml).
Я пробовал использовать тип указателя, но он не работает с этим.
Вот пример упрощенного кода:
https://play.golang.org/p/UheBEPFhzsg

 package main

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

type Config struct {
    Host string        `yaml:"host"`
    Blacklist []string `yaml:"blacklist"`
}

func main() {
    configDataWithBlacklistValues := `
host: localhost
blacklist: 
  - try
  - experiment
`
    configDataWithoutBlacklistValues := `
host: localhost
blacklist:
`
    configDataWithoutBlacklistKey := `
host: localhost
`

    var configWithBlacklistValues Config    // this config should filter out blacklist items
    var configWithoutBlacklistValues Config // this config should filter out everything (no blacklist values = everything to blacklist)
    var configWithoutBlacklistKey Config    // this config should filter out nothing (no blacklist key = nothing to blacklist)

    yaml.Unmarshal(([]byte)(configDataWithBlacklistValues), amp;configWithBlacklistValues)
    yaml.Unmarshal(([]byte)(configDataWithoutBlacklistValues), amp;configWithoutBlacklistValues)
    yaml.Unmarshal(([]byte)(configDataWithoutBlacklistKey), amp;configWithoutBlacklistKey)

    fmt.Printf("% vn", configWithBlacklistValues)
    fmt.Printf("% vn", configWithoutBlacklistValues)
    fmt.Printf("% vn", configWithoutBlacklistKey)
    
    /*
    if blacklist key is not there in yaml:
        then allow everything
    else if blacklist key is there but there are no values:
        then block everything
    else if blacklist values are there in yaml:
        then filter out only the listed items
    */
}
 

Пример кода со списком в качестве типа указателя.
https://play.golang.org/p/wK8i3dLCHWQ

 type HostList []string

type Config struct {
    Host string `yaml:"host"`
    Blacklist *HostList `yaml:"blacklist"`
}
 

Ответ №1:

Простым обходным решением для вашего решения было бы реализовать тип указателя HostList , но закодировать 2) регистр YAML , т. Е. Данные без значений черного списка, как показано ниже

 host: localhost
blacklist: []
 

Таким образом, ваш unmarshal вернет срез нулевой длины ( []string{} ), а не нулевой срез. Таким образом, ваш код может проверить наличие нулевого среза только для 3-го случая.

Иди на детскую площадку