Как проверить значения по умолчанию в Golang, когда yaml уже инициализировал значение? - PullRequest
0 голосов
/ 19 февраля 2019

Я пишу обработчик конфигурации демона и использую для этого пакет yaml.Импортирование моего файла работает следующим образом:

package daemon

import (
    "ioutil"
    "log"

    "gopkg.in/yaml.v2"
)

type daemonConfig struct {
    BindAddress string `yaml:"bind_address"`
    BindPort    int    `yaml:"bind_port"`
    VerifySSL   bool   `yaml:"verify_ssl"`
}

Я легко удаляю данные из моих YAML-файлов следующим образом:

func (config *daemonConfig) getConf() *daemonConfig {
    yamlFile, err := ioutil.ReadFile("config.yaml")
    if err != nil {
        log.Fatal("Unable to open config.yaml:", err)
    }
    err = yaml.Unmarshal(yamlFile, config)
    if err != nil {
        log.Fatal("Failed to unmarshall config.yaml:", err)
    }
    config, err = setDefaults(config)

    return config
}

Мой вопрос касается моей пользовательской функции setDefaults.Если поле не указано, например, bind_port или bind_address, я бы хотел установить для них значения по умолчанию:

func setDefaults(config *daemonConfig) (*daemonConfig, error) {
    if len(config.BindAddress) <= 0 {
        config.BindAddress = "0.0.0.0"
    }
    if config.BindPort == 0 {
        config.BindPort = 9999
    }

    return config, nil
}

Обратите внимание, я не устанавливаю значение по умолчанию verify_ssl;когда yaml отменяет маршалинг этого и не может найти поле, он инициализирует bool как false, что в точности противоположно тому, что я хочу, чтобы поведение по умолчанию было.Я бы предпочел, чтобы пользователь явно отключил проверку SSL, вместо того, чтобы отключить его по умолчанию, если он не указан.Если у меня есть полностью пустой config.yaml, и я ожидаю, что будут установлены значения по умолчанию, он всегда будет содержать verify_ssl как false (этот журнал находится в другом месте приложения):

2019/02/19 03:56:08 Currently loaded config: {0.0.0.0 9999 false}

Как быЯ иду, если это поле не присутствует в полях YAML, которые не маршалируются, чтобы проверить, существует ли линия?Я мог бы просто прочитать файл вручную и сначала проверить этот параметр, но мне было интересно, есть ли более элегантный способ с тем, что у меня есть;в противном случае я просто использую ioutil и проверку строк, чтобы сделать это.Спасибо!

1 Ответ

0 голосов
/ 19 февраля 2019

Благодаря Томасу и mh-cbon Я обнаружил, что могу просто использовать указатель для этого.Если я изменю свое поле VerifySSL на указатель и добавлю omitempty:

type daemonConfig struct {
    BindAddress string `yaml:"bind_address"`
    BindPort    int    `yaml:"bind_port"`
    VerifySSL   *bool  `yaml:"verify_ssl",omitempty`
}

, я могу просто разыменовать поле в структуре, чтобы получить истинное значение того, что yaml не маршалируется.Установить значения по умолчанию так же просто, как:

func setDefaults(config *daemonConfig) (*daemonConfig, error) {
    if len(config.BindAddress) <= 0 {
        config.BindAddress = "0.0.0.0"
    }
    if config.BindPort == 0 {
        config.BindPort = 9999
    }
    if config.VerifySSL == nil {
        ssl := true
        config.VerifySSL = &ssl
    }

    return config, nil
}

Если он загружен в файл, config.VerifySSL будет содержать адрес bool, поэтому он не будет nil, и если он действительновообще отсутствует в файле, тогда поле просто nil, и я могу установить его или получить его с помощью указателя.

РЕДАКТИРОВАТЬ: просто примечание, если ваш указатель VerifySSL равен нулю, вы можете 'присваивать это так:

*config.VerifySSL = true

Разыменование указателя nil.Я обновил решение, добавив в него что-то более управляемое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...