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