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.
# @generateGoEnv(path=env/env.go)The package name follows the output directory (env/env.go → package 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).
Reading values
Section titled “Reading values”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) }}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.
Sharing one instance
Section titled “Sharing one instance”Every Load() call re-parses the blob. To avoid reloading, expose it as a package-level var in your own package:
package config
import "myapp/env"
var Env = mustLoad()
func mustLoad() env.Env { e, err := env.Load() if err != nil { panic(err) } return e}import "myapp/config"
port := config.Env.DbPort // *int64