go
55 lines · 8 steps
Loading typed config from environment variables in Go
A Load function fills a Config struct from environment variables, applying defaults and parsing each value into its proper type.
Explained by
highlit
1package config
2
3import (
4 "fmt"
5 "os"
6 "strconv"
7 "strings"
8 "time"
9)
10
11type Config struct {
12 Host string `env:"HOST"`
13 Port int `env:"PORT"`
14 Debug bool `env:"DEBUG"`
15 ReadTimeout time.Duration `env:"READ_TIMEOUT"`
16 AllowedHosts []string `env:"ALLOWED_HOSTS"`
17}
18
19func Load() (*Config, error) {
20 cfg := &Config{
21 Host: "0.0.0.0",
22 Port: 8080,
23 ReadTimeout: 15 * time.Second,
24 }
25
26 if v, ok := os.LookupEnv("HOST"); ok {
27 cfg.Host = v
28 }
29 if v, ok := os.LookupEnv("PORT"); ok {
30 port, err := strconv.Atoi(v)
31 if err != nil {
32 return nil, fmt.Errorf("PORT: %w", err)
33 }
34 cfg.Port = port
35 }
36 if v, ok := os.LookupEnv("DEBUG"); ok {
37 debug, err := strconv.ParseBool(v)
38 if err != nil {
39 return nil, fmt.Errorf("DEBUG: %w", err)
40 }
41 cfg.Debug = debug
42 }
43 if v, ok := os.LookupEnv("READ_TIMEOUT"); ok {
44 d, err := time.ParseDuration(v)
45 if err != nil {
46 return nil, fmt.Errorf("READ_TIMEOUT: %w", err)
47 }
48 cfg.ReadTimeout = d
49 }
50 if v, ok := os.LookupEnv("ALLOWED_HOSTS"); ok {
51 cfg.AllowedHosts = strings.Split(v, ",")
52 }
53
54 return cfg, nil
55}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Seed a config struct with sensible defaults, then let environment variables override only what's present.
- 2os.LookupEnv distinguishes an unset variable from an empty one, so absent vars keep their defaults untouched.
- 3Wrapping parse errors with the variable name turns a vague failure into an immediately actionable message.
Related explainers
rust
use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(untagged)]
Parsing flexible JSON shapes with serde
deserialization
enums
json
Intermediate
6 steps
ruby
require "shellwords" require "open3" module Backup
Building safe shell commands in Ruby
shell-out
subprocess
command-injection
Intermediate
7 steps
go
package streaming import ( "bufio"
Streaming NDJSON logs over HTTP in Go
http-streaming
channels
select
Advanced
10 steps
typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import * as Joi from 'joi';
Validating env config at boot in NestJS
configuration
schema-validation
environment-variables
Intermediate
8 steps
go
package api import ( "crypto/sha256"
ETag conditional requests in Gin
http-caching
etag
conditional-requests
Intermediate
6 steps
go
func (w *Watcher) resetDebounce(d time.Duration) { if !w.timer.Stop() { select { case <-w.timer.C:
Debouncing a stream of events in Go
debounce
timers
channels
Advanced
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/loading-typed-config-from-environment-variables-in-go-explained-go-2493/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.