SuperProdfor Kubenetes
Tutorial

Getting Started

Quick installation and basic usage

master

Overview
Getting Started with envconfig 1. Install the package go get github.com/kelseyhightower/envconfig 2. Define a config struct type Config struct { ... } 3. Add struct tags envconfig:"FIELD_NAME" 4. Call envconfig.Process() envconfig.Process("APP", &cfg) Error returned? (missing required vars, etc.) Yes Handle error log.Fatal(err) No 5. Use config values cfg.Port, cfg.DBHost, ... Environment Variables PORT=8080 DB_HOST=localhost APP_DEBUG=true Struct tag options default:"8080" required:"true"

This page walks you through installing envconfig and wiring up your first environment-based configuration in a Go application. envconfig maps environment variables directly onto a Go struct using field tags, eliminating the boilerplate of repeated os.Getenv calls and manual type conversions. By the end of this tutorial you will have a working configuration struct that reads from your environment and is ready to extend. If you are building any Go service that needs to respect twelve-factor app principles, this is your starting point.


Prerequisites

Before you begin, make sure you have the following:

  • Go 1.18 or later installed and your GOPATH configured correctly
  • A Go module initialized in your project (go mod init <module-name>)
  • Basic familiarity with Go structs and struct tags
  • Access to a terminal where you can set environment variables

Quick start
  1. Add envconfig to your module:
    go get github.com/kelseyhightower/envconfig
    
  2. Define a struct with envconfig field tags.
  3. Call envconfig.Process to populate the struct from your environment.
  4. Use the resulting values in your application.

The four steps above are everything you need for a working configuration. The sections below explain each one in detail.


Steps

Step 1 — Install envconfig

From your project root, run:

go get github.com/kelseyhightower/envconfig

This adds envconfig to your go.mod and downloads the source. Confirm the dependency was recorded:

grep envconfig go.mod

You should see a line starting with require github.com/kelseyhightower/envconfig.


Step 2 — Define your configuration struct

Create a struct whose fields represent each configuration value your application needs. Use the envconfig struct tag to map a field to a specific environment variable name. Fields without a tag are matched by their uppercased field name by default.

type Config struct {
    Port     int    `envconfig:"PORT"`
    Host     string `envconfig:"HOST"`
    Debug    bool   `envconfig:"DEBUG"`
    LogLevel string `envconfig:"LOG_LEVEL"`
}

Keeping all configuration in one struct makes it easy to see every external dependency your application has at a glance.


Step 3 — Set environment variables

Before running your application, export the variables your struct expects:

export PORT=8080
export HOST=localhost
export DEBUG=true
export LOG_LEVEL=info

In production you would set these through your deployment platform (Docker, Kubernetes, systemd, etc.) rather than exporting them manually.


Step 4 — Process environment variables into the struct

Call envconfig.Process with a prefix and a pointer to your struct. The prefix is prepended to every variable name when envconfig looks up values, which prevents collisions when multiple services share an environment.

package main

import (
    "fmt"
    "log"

    "github.com/kelseyhightower/envconfig"
)

type Config struct {
    Port     int    `envconfig:"PORT"`
    Host     string `envconfig:"HOST"`
    Debug    bool   `envconfig:"DEBUG"`
    LogLevel string `envconfig:"LOG_LEVEL"`
}

func main() {
    var cfg Config
    err := envconfig.Process("MYAPP", &cfg)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Listening on %s:%d (debug=%v, log=%s)\n",
        cfg.Host, cfg.Port, cfg.Debug, cfg.LogLevel)
}

With the prefix "MYAPP", envconfig looks for MYAPP_PORT, MYAPP_HOST, and so on. Update your exports to match:

export MYAPP_PORT=8080
export MYAPP_HOST=localhost
export MYAPP_DEBUG=true
export MYAPP_LOG_LEVEL=info

A successful run prints the resolved values, confirming your struct was populated correctly.


Examples

Basic configuration with a prefix

A complete minimal program that reads four variables and prints the result.

package main

import (
    "fmt"
    "log"

    "github.com/kelseyhightower/envconfig"
)

type Config struct {
    Port     int    `envconfig:"PORT"`
    Host     string `envconfig:"HOST"`
    Debug    bool   `envconfig:"DEBUG"`
    LogLevel string `envconfig:"LOG_LEVEL"`
}

func main() {
    var cfg Config
    if err := envconfig.Process("MYAPP", &cfg); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("host=%s port=%d debug=%v log_level=%s\n",
        cfg.Host, cfg.Port, cfg.Debug, cfg.LogLevel)
}

Set variables and run:

export MYAPP_PORT=8080
export MYAPP_HOST=localhost
export MYAPP_DEBUG=true
export MYAPP_LOG_LEVEL=info
go run main.go

Expected output:

host=localhost port=8080 debug=true log_level=info

Using default values

Annotate fields with default to provide fallback values when an environment variable is not set. This is useful for local development where you may not want to export every variable.

type Config struct {
    Port     int    `envconfig:"PORT" default:"3000"`
    Host     string `envconfig:"HOST" default:"0.0.0.0"`
    Debug    bool   `envconfig:"DEBUG" default:"false"`
    LogLevel string `envconfig:"LOG_LEVEL" default:"warn"`
}

Run without any exports:

go run main.go

Expected output:

host=0.0.0.0 port=3000 debug=false log_level=warn

Marking required variables

Use the required tag to make envconfig return an error if a variable is missing. This fails fast at startup instead of silently using a zero value.

type Config struct {
    DatabaseURL string `envconfig:"DATABASE_URL" required:"true"`
    Port        int    `envconfig:"PORT" default:"8080"`
}

If MYAPP_DATABASE_URL is not set, envconfig.Process returns:

required key MYAPP_DATABASE_URL missing value

Troubleshooting

Variable is not being picked up

Symptom: A struct field stays at its zero value even though you exported the variable.

Likely cause: The environment variable name does not match the expected pattern. envconfig combines your prefix with the field name or envconfig tag value, separated by an underscore.

Fix: Double-check the full variable name. If your prefix is MYAPP and the tag is PORT, the expected variable is MYAPP_PORT. Run env | grep MYAPP to list what is actually set in your shell.


Type conversion error at startup

Symptom: envconfig.Process returns an error like envconfig.Process: assigning MYAPP_PORT to Port: converting 'abc' to type int.

Likely cause: The value of the environment variable cannot be parsed into the Go type declared on the struct field.

Fix: Verify the exported value is valid for the target type. For example, PORT must be a valid integer string (8080), and DEBUG must be true or false for a bool field.


Required variable error even though the variable is set

Symptom: You see required key MYAPP_FOO missing value but echo $MYAPP_FOO prints a value.

Likely cause: The variable was exported in a different shell session or sub-shell and is not present in the environment of the current process.

Fix: Export the variable in the same shell session where you run go run or go build. Alternatively, prefix the command inline: MYAPP_FOO=bar go run main.go.


go get cannot find the module

Symptom: go get fails with cannot find module providing package github.com/kelseyhightower/envconfig.

Likely cause: Your Go environment is in GOPATH mode rather than module mode, or there is a network/proxy issue.

Fix: Ensure your project has a go.mod file (go mod init <name> if not). If you are behind a corporate proxy, set GONOSUMCHECK or GOFLAGS appropriately, or use GOFLAGS=-mod=mod.