Handling Environment Variables in Go Applications

80 views

In Go, you can use environment variables to configure your application without hardcoding values. This allows configuration settings to be separated from the code and to be easily modified without changing the application itself. The standard library os package provides a simple and effective way to handle environment variables.

Setting Environment Variables

Environment variables can be set in different ways depending on your operating system and context:

Linux/macOS:

export APP_ENV=production
export DB_HOST=localhost

Windows:

setx APP_ENV production
setx DB_HOST localhost

Within a Docker container: You can also set environment variables in a Dockerfile or docker-compose.yml file.

Reading Environment Variables

The os package provides functions like os.Getenv, os.Setenv, and os.LookupEnv to interact with environment variables.

  1. os.Getenv: This function retrieves the value of the specified environment variable. If the variable is not set, it returns an empty string.

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        appEnv := os.Getenv("APP_ENV")
        dbHost := os.Getenv("DB_HOST")
    
        fmt.Printf("APP_ENV: %s\n", appEnv) // Output: APP_ENV: production
        fmt.Printf("DB_HOST: %s\n", dbHost) // Output: DB_HOST: localhost
    }
    
  2. os.Setenv: This function sets the value of an environment variable.

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        // Set environment variable
        err := os.Setenv("API_KEY", "your_api_key_here")
        if err != nil {
            fmt.Println("Error setting environment variable:", err)
        }
    
        // Retrieve and print environment variable
        apiKey := os.Getenv("API_KEY")
        fmt.Printf("API_KEY: %s\n", apiKey) // Output: API_KEY: your_api_key_here
    }
    
  3. os.LookupEnv: This function returns the value of the specified environment variable and a boolean indicating whether the variable is set.

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        dbHost, ok := os.LookupEnv("DB_HOST")
        if ok {
            fmt.Printf("DB_HOST: %s\n", dbHost) // Output: DB_HOST: localhost
        } else {
            fmt.Println("DB_HOST is not set")
        }
    }
    

Handling Default Values

Since os.Getenv returns an empty string if the environment variable is not set, you may want to handle default values:

package main

import (
    "fmt"
    "os"
)

func getEnv(key, defaultValue string) string {
    if value, ok := os.LookupEnv(key); ok {
        return value
    }
    return defaultValue
}

func main() {
    appEnv := getEnv("APP_ENV", "development")
    dbHost := getEnv("DB_HOST", "127.0.0.1")

    fmt.Printf("APP_ENV: %s\n", appEnv) // Output: APP_ENV: production (if set) or default: development
    fmt.Printf("DB_HOST: %s\n", dbHost) // Output: DB_HOST: localhost (if set) or default: 127.0.0.1
}

Loading Environment Variables from a File

You can use third-party packages like godotenv to load environment variables from a .env file. This is particularly useful for development and testing.

  1. Install Godotenv:

    go get github.com/joho/godotenv
    
  2. Create a .env File:

    APP_ENV=production
    DB_HOST=localhost
    
  3. Load the .env File in Your Application:

    package main
    
    import (
        "fmt"
        "log"
        "os"
    
        "github.com/joho/godotenv"
    )
    
    func main() {
        err := godotenv.Load()
        if err != nil {
            log.Fatal("Error loading .env file")
        }
    
        appEnv := os.Getenv("APP_ENV")
        dbHost := os.Getenv("DB_HOST")
    
        fmt.Printf("APP_ENV: %s\n", appEnv) // Output: APP_ENV: production
        fmt.Printf("DB_HOST: %s\n", dbHost) // Output: DB_HOST: localhost
    }
    

Practical Example

A more comprehensive example that includes setting and getting environment variables along with using a utility function for default values:

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/joho/godotenv"
)

func getEnv(key, defaultValue string) string {
    if value, ok := os.LookupEnv(key); ok {
        return value
    }
    return defaultValue
}

func main() {
    // Load .env file
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    // Set an environment variable
    os.Setenv("API_KEY", "your_api_key_here")

    // Get environment variables
    appEnv := getEnv("APP_ENV", "development")
    dbHost := getEnv("DB_HOST", "127.0.0.1")
    apiKey := os.Getenv("API_KEY")

    // Output the results
    fmt.Printf("APP_ENV: %s\n", appEnv)
    fmt.Printf("DB_HOST: %s\n", dbHost)
    fmt.Printf("API_KEY: %s\n", apiKey)
}

Conclusion

Using environment variables in Go is straightforward with the os package. For development and testing, tools like godotenv can simplify the process of loading environment variables from files. By handling default values and using utility functions, you can make your Go applications more flexible and configurable.