How to use environment variables in Go (get, set, expand)
Table of Contents
Environment variables are key-value strings provided by the operating system. They are commonly used to pass configuration into Go programs without hard-coding secrets or settings. In Go, you work with them through the standard os package.
Each variable has a key (like APP_PORT) and a value (like 8080). Environment variables are scoped to the current process and are inherited by child processes, which is why tools like Docker and CI pipelines rely on them.
Read environment variables safely #
Use os.LookupEnv to tell the difference between an empty value and a missing variable. If you only use os.Getenv, a missing variable looks the same as an empty one. You can also build a small helper to provide defaults.
package main
import (
"fmt"
"os"
)
func getenvDefault(key, fallback string) string {
if val, ok := os.LookupEnv(key); ok {
return val
}
return fallback
}
func main() {
_ = os.Setenv("APP_EMPTY", "")
_ = os.Setenv("APP_PORT", "8080")
fmt.Printf("Getenv(APP_EMPTY): %q\n", os.Getenv("APP_EMPTY"))
val, ok := os.LookupEnv("APP_EMPTY")
fmt.Printf("LookupEnv(APP_EMPTY): ok=%t value=%q\n", ok, val)
fmt.Printf("APP_PORT with default: %s\n", getenvDefault("APP_PORT", "3000"))
fmt.Printf("APP_MISSING with default: %s\n", getenvDefault("APP_MISSING", "3000"))
}
Output:
Getenv(APP_EMPTY): ""
LookupEnv(APP_EMPTY): ok=true value=""
APP_PORT with default: 8080
APP_MISSING with default: 3000
Set and unset variables #
os.Setenv and os.Unsetenv affect only the current process (and its children), not your shell. If you need a variable available in your shell, set it with export or your shell config file.
package main
import (
"fmt"
"os"
)
func main() {
const key = "APP_TOKEN"
if err := os.Setenv(key, "secret-123"); err != nil {
panic(err)
}
fmt.Printf("After Setenv: %s=%s\n", key, os.Getenv(key))
if err := os.Unsetenv(key); err != nil {
panic(err)
}
_, ok := os.LookupEnv(key)
fmt.Printf("After Unsetenv: ok=%t\n", ok)
}
Output:
After Setenv: APP_TOKEN=secret-123
After Unsetenv: ok=false
List variables and clear the environment #
Use os.Environ to list the process environment. os.Clearenv removes everything for the current process. This is handy for short-lived tools and tests.
package main
import (
"fmt"
"os"
"strings"
)
func main() {
_ = os.Setenv("APP_NAME", "gosamples")
_ = os.Setenv("APP_ENV", "dev")
count := 0
for _, env := range os.Environ() {
if strings.HasPrefix(env, "APP_") {
fmt.Println(env)
count++
}
}
fmt.Printf("APP_ variables: %d\n", count)
os.Clearenv()
fmt.Printf("After Clearenv: %d variables\n", len(os.Environ()))
}
Output:
APP_NAME=gosamples
APP_ENV=dev
APP_ variables: 2
After Clearenv: 0 variables
Expand variables in strings (related utilities) #
Use os.ExpandEnv for $VAR or ${VAR} expansion, and os.Expand when you want custom handling (for example, a fallback value).
package main
import (
"fmt"
"os"
)
func main() {
_ = os.Setenv("APP_HOME", "/srv/app")
_ = os.Setenv("USER", "gosamples")
fmt.Println(os.ExpandEnv("$APP_HOME/logs"))
expanded := os.Expand("User=${USER}, app=${APP_NAME}", func(key string) string {
if key == "APP_NAME" {
return "gosamples"
}
return os.Getenv(key)
})
fmt.Println(expanded)
}
Output:
/srv/app/logs
User=gosamples, app=gosamples
Common mistakes #
- ❌ Using
os.Getenvto check if a variable exists. ✅ Useos.LookupEnvto detect missing keys. - ❌ Expecting
os.Setenvto modify your shell environment. ✅ Useexportin the shell for that. - ❌ Calling
os.Clearenvin shared libraries. ✅ Reserve it for tests or short-lived tools.
Best practices #
- Treat environment variables as immutable configuration once your app starts.
- Document required variables and defaults in README or sample config.
- Avoid storing secrets in code; read them from env or a secrets manager.
Related topics #
- Read a YAML file in Go - load configuration files
- Read a file in Go - ingest config from disk
- Write a file in Go - persist generated config
- Check Go version in Go - tooling diagnostics
- Get local IP address in Go - environment info
Tested with Go 1.25+ | Last verified: December 2025 🎉