1

I'm using https://github.com/spf13/viper for configuration manager.

I've come across a use case where I've to use multiple config files .json, .env and environment variables in such a way.

  • First all config from .json is loaded
  • All non-empty variables from .env is loaded. Empty variables on .env or non-existing variables wouldn't override values from .json
  • All non-empty variables from environment variables of platform is loaded. Empty variables on .env or non-existing variables wouldn't override values from .json

For the same purpose, I tried with following snippet but doesn't seem to work.

package main

import (
    "github.com/spf13/viper"
    "log"
)

type ServerConfiguration struct {
    Port int
}

type DatabaseConfiguration struct {
    ConnectionUri string
}

type Configuration struct {
    Server   ServerConfiguration
    Database DatabaseConfiguration
}

func main() {
    var configuration Configuration
    readFromConfigFile()
    readFromEnvFile()
    viper.AutomaticEnv()

    err := viper.Unmarshal(&configuration)
    if err != nil {
        log.Fatalf("unable to decode into struct, %v", err)
    }
    log.Printf("database uri is %s", configuration.Database.ConnectionUri)
    log.Printf("port for this application is %d", configuration.Server.Port)
}

func readFromConfigFile() {
    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalf("Error reading config file, %s", err)
    }
}

func readFromEnvFile() {
    viper.SetConfigName(".env")
    viper.SetConfigType("env")
    viper.AddConfigPath(".")
    if err := viper.MergeInConfig(); err != nil {
        log.Fatalf("Error reading config file, %s", err)
    }
}
{
    "database": {
        "connectionUri": "test uri"
    },
    "server": {
        "port": 8283
    }
}
DATABASE_CONNECTION_URI="test2 uri"

Expected result:

2023/03/15 17:07:42 database uri is test2 uri
2023/03/15 17:07:42 port for this application is 8283

Actual result:

2023/03/15 17:07:42 database uri is test uri
2023/03/15 17:07:42 port for this application is 8283

I tried with the suggestion mentioned here but didn't help

Multiple config files with go-viper

Is it possible to attain as mentioned? If so, how could I achieve the functionality

Sujit Baniya
  • 895
  • 9
  • 27

1 Answers1

0

github.com/spf13/viper fits your requirement perfectly.

The issue here is that the key in .env is incorrect. The default key delimiter is . (see the source code). So the key should be DATABASE.CONNECTIONURI. Here is the corrected configuration (please note that _ in CONNECTION_URI should be removed too):

DATABASE.CONNECTIONURI="test2 uri"
Zeke Lu
  • 6,349
  • 1
  • 17
  • 23