Getting Started
How to get started with this product
This page walks you through installing envconfig and wiring it up to load your application's configuration from environment variables in minutes. envconfig reads environment variables and automatically populates a Go struct, so you can configure your application at runtime without touching your code. By the end of this tutorial you will have a working Go program that reads typed configuration values—including strings, integers, durations, slices, and maps—directly from the environment.
Before you begin, make sure you have the following:
- Go 1.11 or later installed and a working Go module project (
go mod inithas been run) - Basic familiarity with Go structs and the
go getcommand - A terminal where you can set environment variables (
exporton macOS/Linux,setor$env:on Windows PowerShell)
The steps below take you from an empty project to a running configuration loader.
-
Add envconfig to your project
go get github.com/kelseyhightower/envconfig -
Set the required 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" -
Create
main.gowith the code shown in the Examples section below. -
Run the program
go run main.goYou should see your configuration values printed to stdout, confirming that envconfig read them from the environment.
Follow these steps to build a complete configuration-loading setup from scratch.
Step 1 — Install the library
From inside your Go module directory, run:
go get github.com/kelseyhightower/envconfig
This adds github.com/kelseyhightower/envconfig to your go.mod and go.sum files. You only need to do this once per project.
Step 2 — Define a configuration struct
Create a struct whose fields represent the values your application needs. envconfig maps each field to an environment variable automatically: it uppercases the field name and prepends the application prefix you supply at runtime.
type Specification struct {
Debug bool
Port int
User string
Users []string
Rate float32
Timeout time.Duration
ColorCodes map[string]int
}
For example, the Port field maps to MYAPP_PORT when you use the prefix "myapp". envconfig handles type conversion for you, so the string "8080" in the environment becomes the integer 8080 in your struct.
Step 3 — Call envconfig.Process
In your main function, declare a zero-value struct and pass a pointer to envconfig.Process along with your chosen prefix:
var s Specification
err := envconfig.Process("myapp", &s)
if err != nil {
log.Fatal(err.Error())
}
The prefix ("myapp") is prepended to every environment variable name. Using a prefix prevents conflicts with other programs running in the same environment. If Process returns an error—for example because a required variable is missing or a value cannot be converted—it is safe to treat this as a fatal startup error.
Step 4 — Set environment variables and run
Set each variable in your terminal using the PREFIX_FIELDNAME convention, then run your program:
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"
go run main.go
If the program prints your configuration values without error, the setup is working correctly.
Step 5 — (Optional) Add struct tags for richer control
Once the basics work, you can refine behavior with struct tags:
envconfig:"MY_VAR"— maps the field to a specific variable name instead of the derived default.default:"value"— supplies a fallback when the variable is not set.required:"true"— causesProcessto return an error if the variable is absent.split_words:"true"— splits a CamelCase field name intoUPPER_SNAKE_CASEautomatically.ignored:"true"— tells envconfig to skip the field entirely.
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"`
}
Example 1 — Full working program
This program loads all supported basic types from the environment and prints them.
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)
}
}
With the environment variables from the quickstart set, running this program produces:
Debug: false
Port: 8080
User: Kelsey
Rate: 0.500000
Timeout: 3m0s
Users:
rob
ken
robert
Color codes:
red: 1
green: 2
blue: 3
Example 2 — Struct tags for defaults and required fields
This example shows how to declare a default value and mark a field as required. If MYAPP_REQUIREDVAR is not set, envconfig.Process returns an error and the program exits.
type Specification struct {
DefaultVar string `default:"foobar"`
RequiredVar string `required:"true"`
}
Set only the required variable and observe the default being used:
export MYAPP_REQUIREDVAR="hello"
go run main.go
DefaultVar will be populated with "foobar" because no environment variable was set for it.
Example 3 — CamelCase splitting with split_words
Without split_words:"true", a field named AutoSplitVar resolves to MYAPP_AUTOSPLITVAR. With the tag, it resolves to MYAPP_AUTO_SPLIT_VAR—which is easier to read and set.
type Specification struct {
AutoSplitVar string `split_words:"true"`
}
export MYAPP_AUTO_SPLIT_VAR="hello"
go run main.go
Issue: envconfig.Process returns an error saying a required variable is missing
- Symptom: Your program exits immediately with a message like
required key MYAPP_REQUIREDVAR missing value. - Cause: A struct field is tagged
required:"true"and the corresponding environment variable was not set before running the program. - Fix: Set the missing variable (
export MYAPP_REQUIREDVAR=somevalue) before running the program. If the variable should be optional, remove therequired:"true"tag or add adefault:"value"tag instead.
Issue: A field stays at its zero value even though the environment variable is set
- Symptom: For example,
Portis0even though you ranexport MYAPP_PORT=8080. - Cause: The environment variable name does not match what envconfig expects. Common causes include: wrong prefix, wrong case, or a CamelCase field name that needs
split_words:"true"to resolve correctly. - Fix: Double-check the variable name. The default pattern is
UPPERCASE_PREFIX+_+UPPERCASE_FIELDNAME. For a field likeColorCodeswith prefixmyapp, the variable should beMYAPP_COLORCODES. If you wantMYAPP_COLOR_CODES, addsplit_words:"true"to the field tag.
Issue: A value cannot be converted and Process returns a parse error
- Symptom: Error message similar to
envconfig.Process: assigning MYAPP_PORT to Port: converting 'abc' to type int. - Cause: The environment variable contains a value that cannot be converted to the field's Go type (for example, a non-numeric string for an
intfield). - Fix: Correct the value of the environment variable so it matches the expected type. Refer to the supported types list—integers, floats, booleans,
time.Duration, slices (comma-separated), and maps (key:valuepairs, comma-separated).
Issue: go get fails or the package is not found
- Symptom:
go get github.com/kelseyhightower/envconfigreturns a network or module error. - Cause: Your project may not be initialized as a Go module, or you may be behind a proxy that blocks the request.
- Fix: Make sure you have run
go mod init <module-name>in your project directory first. If you are behind a corporate proxy, setGOPROXYto an accessible proxy or todirect.
Issue: The ignored:"true" field is still being populated
- Symptom: A field tagged
ignored:"true"appears to receive a value. - Cause: Another part of your code may be setting the field directly, or the tag is misspelled.
- Fix: Verify the tag is exactly
ignored:"true"(lowercase, no spaces). envconfig will not attempt to populate the field from the environment, but your own code can still write to it.