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