Convert Figma logo to code with AI

kelseyhightower logoenvconfig

Golang library for managing configuration data from environment variables

5,006
377
5,006
53

Top Related Projects

A Go port of Ruby's dotenv library (Loads environment variables from .env files)

26,777

Go configuration with fangs

4,762

A simple, zero-dependencies library to parse environment variables into structs

✨Clean and minimalistic environment configuration reader for Golang

2,645

Simple, extremely lightweight, extensible, configuration management library for Go. Support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.

Quick Overview

envconfig is a Go library that simplifies the process of populating struct fields from environment variables. It provides a clean and efficient way to configure applications using environment variables, making it easier to manage configuration across different deployment environments.

Pros

  • Easy to use and integrate into existing Go projects
  • Supports various data types and custom parsing
  • Allows for default values and required fields
  • Minimal external dependencies

Cons

  • Limited to environment variables as the configuration source
  • May require additional setup for complex nested structures
  • Not suitable for applications requiring dynamic configuration changes at runtime
  • Limited built-in support for configuration file formats (e.g., YAML, JSON)

Code Examples

  1. Basic usage:
type Config struct {
    Host     string `envconfig:"HOST" default:"localhost"`
    Port     int    `envconfig:"PORT" default:"8080"`
    LogLevel string `envconfig:"LOG_LEVEL" default:"info"`
}

var cfg Config
err := envconfig.Process("myapp", &cfg)
if err != nil {
    log.Fatal(err)
}
  1. Custom parsing:
type Duration time.Duration

func (d *Duration) Decode(value string) error {
    parsed, err := time.ParseDuration(value)
    if err != nil {
        return err
    }
    *d = Duration(parsed)
    return nil
}

type Config struct {
    Timeout Duration `envconfig:"TIMEOUT" default:"30s"`
}

var cfg Config
err := envconfig.Process("myapp", &cfg)
  1. Required fields:
type Config struct {
    APIKey string `envconfig:"API_KEY" required:"true"`
    Debug  bool   `envconfig:"DEBUG" default:"false"`
}

var cfg Config
err := envconfig.Process("myapp", &cfg)

Getting Started

To use envconfig in your Go project:

  1. Install the library:

    go get github.com/kelseyhightower/envconfig
    
  2. Import it in your code:

    import "github.com/kelseyhightower/envconfig"
    
  3. Define a struct with fields tagged for envconfig:

    type Config struct {
        DatabaseURL string `envconfig:"DATABASE_URL" required:"true"`
        Port        int    `envconfig:"PORT" default:"8080"`
    }
    
  4. Process the configuration:

    var cfg Config
    err := envconfig.Process("myapp", &cfg)
    if err != nil {
        log.Fatal(err)
    }
    
  5. Use the populated struct in your application.

Competitor Comparisons

A Go port of Ruby's dotenv library (Loads environment variables from .env files)

Pros of godotenv

  • Allows loading environment variables from a .env file, which is useful for development and testing
  • Supports multiple .env files and overriding existing environment variables
  • Simple and straightforward API for loading and parsing .env files

Cons of godotenv

  • Focuses primarily on loading variables from files, not on parsing or type conversion
  • Doesn't provide struct tag-based configuration like envconfig
  • May require additional code for type conversion and validation

Code Comparison

godotenv:

err := godotenv.Load()
if err != nil {
    log.Fatal("Error loading .env file")
}
s3Bucket := os.Getenv("S3_BUCKET")

envconfig:

type Config struct {
    S3Bucket string `envconfig:"S3_BUCKET"`
}
var c Config
err := envconfig.Process("myapp", &c)

Summary

godotenv is ideal for projects that need to load environment variables from files, especially during development. It's simple to use but requires manual handling of variable types. envconfig, on the other hand, provides more robust parsing and type conversion capabilities, making it suitable for applications with complex configuration needs. The choice between the two depends on the specific requirements of your project and your preferred approach to configuration management.

26,777

Go configuration with fangs

Pros of Viper

  • Supports multiple configuration sources (environment variables, config files, command-line flags)
  • Offers live watching and automatic reloading of configuration files
  • Provides a rich set of features like setting defaults, aliases, and type-safe settings

Cons of Viper

  • More complex setup and usage compared to Envconfig's simplicity
  • Larger codebase and dependencies, potentially increasing build size
  • May be overkill for simple projects that only need environment variable configuration

Code Comparison

Envconfig:

type Config struct {
    Host string `envconfig:"HOST"`
    Port int    `envconfig:"PORT"`
}

var c Config
err := envconfig.Process("myapp", &c)

Viper:

viper.SetEnvPrefix("myapp")
viper.AutomaticEnv()
viper.SetConfigName("config")
viper.AddConfigPath(".")
err := viper.ReadInConfig()

host := viper.GetString("host")
port := viper.GetInt("port")

Envconfig focuses solely on environment variables with a straightforward struct-based approach, while Viper offers a more flexible and feature-rich configuration management system at the cost of increased complexity.

4,762

A simple, zero-dependencies library to parse environment variables into structs

Pros of env

  • Supports parsing of slices, maps, and time.Duration
  • Offers custom parsers for more complex types
  • Provides options for prefix stripping and environment variable name customization

Cons of env

  • Slightly more complex API compared to envconfig
  • May require more setup for advanced use cases
  • Less widespread adoption in the Go community

Code Comparison

envconfig:

type Config struct {
    Port int `envconfig:"PORT"`
    Debug bool `envconfig:"DEBUG"`
}

var c Config
err := envconfig.Process("myapp", &c)

env:

type Config struct {
    Port int `env:"PORT"`
    Debug bool `env:"DEBUG"`
}

var c Config
err := env.Parse(&c)

Summary

Both envconfig and env are popular libraries for parsing environment variables in Go applications. envconfig is known for its simplicity and widespread adoption, while env offers more advanced features like custom parsers and support for complex types. The choice between the two depends on the specific requirements of your project and the level of customization needed for environment variable parsing.

✨Clean and minimalistic environment configuration reader for Golang

Pros of cleanenv

  • Supports multiple configuration sources (environment variables, config files, flags)
  • Offers built-in validation and custom validation functions
  • Provides a more feature-rich and flexible configuration solution

Cons of cleanenv

  • May have a steeper learning curve due to additional features
  • Potentially higher overhead for simple use cases
  • Less established and battle-tested compared to envconfig

Code Comparison

envconfig:

type Config struct {
    Port int `envconfig:"PORT"`
    Debug bool `envconfig:"DEBUG"`
}

var c Config
err := envconfig.Process("myapp", &c)

cleanenv:

type Config struct {
    Port int `env:"PORT" env-default:"8080"`
    Debug bool `env:"DEBUG" env-default:"false"`
}

var c Config
err := cleanenv.ReadEnv(&c)

Both libraries offer similar basic functionality for reading environment variables into struct fields. However, cleanenv provides additional features like default values and supports multiple configuration sources.

cleanenv is more versatile and feature-rich, making it suitable for complex configuration scenarios. envconfig, on the other hand, is simpler and more focused on environment variables, which may be preferable for straightforward use cases or when minimal dependencies are desired.

The choice between the two depends on the specific requirements of your project, such as the need for multiple configuration sources, validation, or simplicity.

2,645

Simple, extremely lightweight, extensible, configuration management library for Go. Support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.

Pros of koanf

  • Supports multiple configuration sources (environment variables, files, command-line flags)
  • Offers advanced features like type conversion, default values, and nested structures
  • Provides a more flexible and extensible configuration management system

Cons of koanf

  • More complex setup and usage compared to envconfig's simplicity
  • Steeper learning curve due to its extensive feature set
  • Potentially overkill for small projects with simple configuration needs

Code Comparison

envconfig:

type Config struct {
    Host string `envconfig:"HOST"`
    Port int    `envconfig:"PORT"`
}

var cfg Config
err := envconfig.Process("myapp", &cfg)

koanf:

var k = koanf.New(".")
k.Load(file.Provider("config.yaml"), yaml.Parser())
k.Load(env.Provider("MYAPP_", ".", func(s string) string {
    return strings.Replace(strings.ToLower(s), "_", ".", -1)
}), nil)

var cfg Config
err := k.Unmarshal("", &cfg)

The code comparison demonstrates that envconfig is more straightforward for simple environment variable parsing, while koanf offers more flexibility in configuration sources and parsing options. koanf requires more setup but provides greater control over the configuration process.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

envconfig

Build Status

import "github.com/kelseyhightower/envconfig"

Documentation

See godoc

Usage

Set some environment variables:

export MYAPP_DEBUG=false
export MYAPP_PORT=8080
export MYAPP_USER=Kelsey
export MYAPP_RATE="0.5"
export MYAPP_TIMEOUT="3m"
export MYAPP_USERS="rob,ken,robert"
export MYAPP_COLORCODES="red:1,green:2,blue:3"

Write some code:

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/kelseyhightower/envconfig"
)

type Specification struct {
    Debug       bool
    Port        int
    User        string
    Users       []string
    Rate        float32
    Timeout     time.Duration
    ColorCodes  map[string]int
}

func main() {
    var s Specification
    err := envconfig.Process("myapp", &s)
    if err != nil {
        log.Fatal(err.Error())
    }
    format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n"
    _, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout)
    if err != nil {
        log.Fatal(err.Error())
    }

    fmt.Println("Users:")
    for _, u := range s.Users {
        fmt.Printf("  %s\n", u)
    }

    fmt.Println("Color codes:")
    for k, v := range s.ColorCodes {
        fmt.Printf("  %s: %d\n", k, v)
    }
}

Results:

Debug: false
Port: 8080
User: Kelsey
Rate: 0.500000
Timeout: 3m0s
Users:
  rob
  ken
  robert
Color codes:
  red: 1
  green: 2
  blue: 3

Struct Tag Support

Envconfig supports the use of struct tags to specify alternate, default, and required environment variables.

For example, consider the following struct:

type Specification struct {
    ManualOverride1 string `envconfig:"manual_override_1"`
    DefaultVar      string `default:"foobar"`
    RequiredVar     string `required:"true"`
    IgnoredVar      string `ignored:"true"`
    AutoSplitVar    string `split_words:"true"`
    RequiredAndAutoSplitVar    string `required:"true" split_words:"true"`
}

Envconfig has automatic support for CamelCased struct elements when the split_words:"true" tag is supplied. Without this tag, AutoSplitVar above would look for an environment variable called MYAPP_AUTOSPLITVAR. With the setting applied it will look for MYAPP_AUTO_SPLIT_VAR. Note that numbers will get globbed into the previous word. If the setting does not do the right thing, you may use a manual override.

Envconfig will process value for ManualOverride1 by populating it with the value for MYAPP_MANUAL_OVERRIDE_1. Without this struct tag, it would have instead looked up MYAPP_MANUALOVERRIDE1. With the split_words:"true" tag it would have looked up MYAPP_MANUAL_OVERRIDE1.

export MYAPP_MANUAL_OVERRIDE_1="this will be the value"

# export MYAPP_MANUALOVERRIDE1="and this will not"

If envconfig can't find an environment variable value for MYAPP_DEFAULTVAR, it will populate it with "foobar" as a default value.

If envconfig can't find an environment variable value for MYAPP_REQUIREDVAR, it will return an error when asked to process the struct. If MYAPP_REQUIREDVAR is present but empty, envconfig will not return an error.

If envconfig can't find an environment variable in the form PREFIX_MYVAR, and there is a struct tag defined, it will try to populate your variable with an environment variable that directly matches the envconfig tag in your struct definition:

export SERVICE_HOST=127.0.0.1
export MYAPP_DEBUG=true
type Specification struct {
    ServiceHost string `envconfig:"SERVICE_HOST"`
    Debug       bool
}

Envconfig won't process a field with the "ignored" tag set to "true", even if a corresponding environment variable is set.

Supported Struct Field Types

envconfig supports these struct field types:

Embedded structs using these fields are also supported.

Custom Decoders

Any field whose type (or pointer-to-type) implements envconfig.Decoder can control its own deserialization:

export DNS_SERVER=8.8.8.8
type IPDecoder net.IP

func (ipd *IPDecoder) Decode(value string) error {
    *ipd = IPDecoder(net.ParseIP(value))
    return nil
}

type DNSConfig struct {
    Address IPDecoder `envconfig:"DNS_SERVER"`
}

Example for decoding the environment variables into map[string][]structName type

export SMS_PROVIDER_WITH_WEIGHT= `IND=[{"name":"SMSProvider1","weight":70},{"name":"SMSProvider2","weight":30}];US=[{"name":"SMSProvider1","weight":100}]`
type providerDetails struct {
	Name   string
	Weight int
}

type SMSProviderDecoder map[string][]providerDetails

func (sd *SMSProviderDecoder) Decode(value string) error {
	smsProvider := map[string][]providerDetails{}
	pairs := strings.Split(value, ";")
	for _, pair := range pairs {
		providerdata := []providerDetails{}
		kvpair := strings.Split(pair, "=")
		if len(kvpair) != 2 {
			return fmt.Errorf("invalid map item: %q", pair)
		}
		err := json.Unmarshal([]byte(kvpair[1]), &providerdata)
		if err != nil {
			return fmt.Errorf("invalid map json: %w", err)
		}
		smsProvider[kvpair[0]] = providerdata

	}
	*sd = SMSProviderDecoder(smsProvider)
	return nil
}

type SMSProviderConfig struct {
    ProviderWithWeight SMSProviderDecoder `envconfig:"SMS_PROVIDER_WITH_WEIGHT"`
}

Also, envconfig will use a Set(string) error method like from the flag.Value interface if implemented.