I need to read data first of all from the fields inside the service, and only then look at the external fields.

存在此类型的配置:

auth_service:
  log_level: debug
  port: 9999
mail_service:
  log_level: debug
  port: 9998
smtp:
  host: localhost
  port: 1025
  username: ""
  password: ""
  email_from: "mailservice@test.test"
  retries_count: 5
log_level: test

我试图通过viper.RegisterAlias("log_level", "auth_service.log_level")来实现,但在这种形式下,外部字段是不能读取的.

获取配置的代码如下:

type Config struct  {
    LogLevel string `mapstructure:"log_level"`
    Port int `mapstructure:"port"`
    SMTP SMTPConfig `mapstructure:"smtp"`
}

type SMTPConfig struct {
    Host         string     `mapstructure:"host"`
    Port         int        `mapstructure:"port"`
    Username     string     `mapstructure:"username"`
    Password     string     `mapstructure:"password"`
    EmailFrom    string     `mapstructure:"email_from"`
    RetriesCount int        `mapstructure:"retries_count"`
}

func LoadConfig(path string) (*Config, error) {
    type ServiceConfig struct {
        Cfg Config `mapstructure:"auth_service"`
    }
    viper.RegisterAlias("log_level","auth_service.log_level")
    viper.AutomaticEnv()
    if path != "" {
        dir := p.Dir(path)
        file := p.Base(path)
        fileParts := strings.Split(file, ".")
        if len(fileParts) != 2 {
            return nil, fmt.Errorf("incorrect config file: %s", file)
        }
        viper.AddConfigPath(dir)
        viper.SetConfigName(fileParts[0])
        viper.SetConfigType(fileParts[1])
        err := viper.ReadInConfig()
        if err != nil {
            return nil, err
        }
    }
    fmt.Println(viper.AllKeys())
    var config ServiceConfig
    err := viper.Unmarshal(&config)
    if err != nil {
        return nil, err
    }
    return &config.Cfg, nil
}

需要ServiceConfig,这样您才能从SERVICE_NAME_FIELD_NAME获得值,因为mapstructure:"service_name.field"不起作用.

推荐答案

在深入研究之后,我意识到没有本机的方法来解决这一问题,我必须创建一个分支并添加一些代码. 现在,您可以配置Viper,以便首先读取密钥中的数据,然后才判断别名. 还增加了逐级验证别名的可能性.

https://github.com/EwvwGeN/viper

当然,您可以使用反射包来实现这一点,例如,通过在字段中指定您的新标记alias: "field_one, field_two",但对我来说,创建一个成熟的fork会更方便

感谢大家给这个问题打分

Go相关问答推荐

Go 1.22 net/http群组路由

如何使用Docker Compose配置Go,使main. go文件位于/CMD文件夹中

Go协议缓冲区导入问题

Go 中的sync.Cond 与 Wait 方法

Go 中的 protobuf FieldMask 解组

这是实现超时的常见方法,为什么 time.After 不起作用

我的神经网络(从头开始)训练,让它离目标更远

golang 上基于标头的版本控制

emersion/go-imap - imap.FetchRFC822:无效内存地址或零指针取消引用

无法使用 Golang 扫描文件路径

致命错误:找不到由 zergon321/reisen 引起的libavcodec/avcodec.h文件

如何修改go gin的默认端口?我的 8080 端口正在使用中

将 .gz 文件添加到 tar.gz 文件,但在添加之前解码 gz.输出文件被剪辑(损坏)

如何使用 Status 字段创建 Kubernetes 对象?

如何 Select 前 N 个元素 Gin-Gorm

将 CSVExport 函数传递给处理程序 Gin

GOENV 只能使用 OS 环境设置

gopls 为 github.com/Shopify/sarama 返回错误gopls: no packages returned: packages.Load error

不能使用 *T 类型的变量作为参数类型

关于GO的几个问题