title: Reading in environmental Variable Using Viper Go
body: <p>I am trying to make Viper read my environment variables, but its not working. Here is my configuration:</p>
  
  <pre><code># app.yaml
  dsn: RESTFUL_APP_DSN
  jwt_verification_key: RESTFUL_APP_JWT_VERIFICATION_KEY
  jwt_signing_key: RESTFUL_APP_JWT_SIGNING_KEY
  jwt_signing_method: "HS256"
  </code></pre>
  
  <p>And my <code>config.go</code> file:</p>
  
  <pre><code>package config
  
  import (
      "fmt"
      "strings"
  
      "github.com/go-ozzo/ozzo-validation"
      "github.com/spf13/viper"
  )
  
  // Config stores the application-wide configurations
  var Config appConfig
  
  type appConfig struct {
      // the path to the error message file. Defaults to "config/errors.yaml"
      ErrorFile string `mapstructure:"error_file"`
      // the server port. Defaults to 8080
      ServerPort int `mapstructure:"server_port"`
      // the data source name (DSN) for connecting to the database. required.
      DSN string `mapstructure:"dsn"`
      // the signing method for JWT. Defaults to "HS256"
      JWTSigningMethod string `mapstructure:"jwt_signing_method"`
      // JWT signing key. required.
      JWTSigningKey string `mapstructure:"jwt_signing_key"`
      // JWT verification key. required.
      JWTVerificationKey string `mapstructure:"jwt_verification_key"`
  }
  
  func (config appConfig) Validate() error {
      return validation.ValidateStruct(&amp;config,
          validation.Field(&amp;config.DSN, validation.Required),
          validation.Field(&amp;config.JWTSigningKey, validation.Required),
          validation.Field(&amp;config.JWTVerificationKey, validation.Required),
      )
  }
  
  func LoadConfig(configpaths ...string) error {
      v := viper.New()
      v.SetConfigName("app")
      v.SetConfigType("yaml")
      v.SetEnvPrefix("restful")
      v.AutomaticEnv()
      v.SetDefault("error_file", "config/errors.yaml")
      v.SetDefault("server_port", 1530)
      v.SetDefault("jwt_signing_method", "HS256")
      v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
  
      for _, path := range configpaths {
          v.AddConfigPath(path)
      }
  
      if err := v.ReadInConfig(); err != nil {
          return fmt.Errorf("Failed to read the configuration file: %s", err)
      }
  
      if err := v.Unmarshal(&amp;Config); err != nil {
          return err
      }
  
      // Checking with this line. This is what I get:
      // RESTFUL_JWT_SIGNING_KEY
      fmt.Println("Sign Key: ", v.GetString("jwt_signing_key"))
  
      return Config.Validate()
  }
  </code></pre>
  
  <p>This line <code>fmt.Println("Sign Key: ", v.GetString("jwt_signing_key"))</code> gives me just the key passed in the yaml file <code>RESTFUL_JWT_SIGNING_KEY</code>. I don't know what I'm doing wrong.</p>
  
  <p>According to doc:</p>
  
  <blockquote>
    <p>AutomaticEnv is a powerful helper especially when combined with
    SetEnvPrefix. When called, Viper will check for an environment
    variable any time a viper.Get request is made. It will apply the
    following rules. It will check for a environment variable with a name
    matching the key uppercased and prefixed with the EnvPrefix if set.</p>
  </blockquote>
  
  <p>So, why isn't it reading the environment variables?</p>
  
  <p>Using <code>JSON</code></p>
  
  <pre><code>{
    "dsn": "RESTFUL_APP_DSN",
    "jwt_verification_key": "RESTFUL_APP_JWT_VERIFICATION_KEY",
    "jwt_signing_key": "RESTFUL_APP_JWT_SIGNING_KEY",
    "jwt_signing_method": "HS256"
  }
  </code></pre>
  
  <p>And my parser looks like thus:</p>
  
  <pre><code>// LoadConfigEnv loads configuration from the given list of paths and populates it into the Config variable.
  // Environment variables with the prefix "RESTFUL_" in their names are also read automatically.
  func LoadConfigEnv(environment string, configpaths ...string) error {
    v := viper.New()
    v.SetConfigName(environment)
    v.SetConfigType("json")
    v.SetEnvPrefix("restful")
    v.AutomaticEnv()
    v.SetDefault("jwt_signing_method", "HS256")
    v.SetDefault("error_file", "config/errors.yaml")
    v.SetDefault("server_port", 1530)
    v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
  
    for _, path := range configpaths {
      v.AddConfigPath(path)
    }
  
    if err := v.ReadInConfig(); err != nil {
      return fmt.Errorf("Failed to read the configuration file: %s", err)
    }
  
    if err := v.Unmarshal(&amp;Config); err != nil {
      return err
    }
  
    return Config.Validate()
  }
  </code></pre>
  
  <p>In the <code>Validate</code> function, I decided to check the <code>Config</code> struct, and this is what I got:</p>
  
  <p><code>Config:  {config/errors.yaml 1530 RESTFUL_APP_DSN HS256 RESTFUL_APP_JWT_SIGNING_KEY RESTFUL_APP_JWT_VERIFICATION_KEY}</code></p>