Skip to content

Go

To use varlock with Go, install the standalone binary and run your app under varlock run. It loads and validates your env, then injects it into the process.

Add @generateGoEnv to your schema to generate a small, self-contained package: an Env struct, a Load() function that parses the injected __VARLOCK_ENV blob, and a SensitiveKeys map.

.env.schema
# @generateGoEnv(path=env/env.go)

The package name follows the output directory (env/env.gopackage env); override it with package=. The file is regenerated automatically on varlock load and varlock run, or explicitly with varlock codegen. Requires Go 1.18+ (the generated code uses any).

Call Load() once, then read fields off the struct. Required fields are the plain type, optional ones are pointers (deref when set):

package main
import (
"log"
"myapp/env"
)
func main() {
e, err := env.Load() // call once, hold or pass `e` around
if err != nil {
log.Fatal(err)
}
host := e.DbHost // string (required field)
if e.DbPort != nil { // *int64 (optional field, deref when set)
log.Printf("%s:%d", host, *e.DbPort)
}
}
Terminal window
varlock run -- go run .

Load() returns a clear error if __VARLOCK_ENV is missing (e.g. you forgot varlock run) or if a required key is absent.

Every Load() call re-parses the blob. To avoid reloading, expose it as a package-level var in your own package:

config/config.go
package config
import "myapp/env"
var Env = mustLoad()
func mustLoad() env.Env {
e, err := env.Load()
if err != nil {
panic(err)
}
return e
}
anywhere.go
import "myapp/config"
port := config.Env.DbPort // *int64