Go SDK Guide
This guide covers adding Liteguard to a Go application.
Prerequisites
- A Project Client Token from your Liteguard project. Follow the Getting Started guide through the Copy a Project Client Token step if you do not have one yet.
- Go 1.21 or later.
Install the SDK
go get github.com/liteguard/liteguardInitialize the client
Create a Client during application startup and shut it down when the process exits.
package main
import (
"context"
"log"
"os"
"github.com/liteguard/liteguard"
)
func main() {
client, err := liteguard.NewClient(os.Getenv("LITEGUARD_TOKEN"), nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
// ...
}NewClient fetches the initial bundle before returning, so the client is ready to evaluate guards immediately.
Do not commit your token to source control. Read it from an environment variable or secrets manager.
Environment
client, err := liteguard.NewClient(
os.Getenv("LITEGUARD_TOKEN"),
&liteguard.ClientOptions{
Environment: os.Getenv("LITEGUARD_ENV"),
},
)The slug must match one of the environments defined in your workspace. Slugs are visible in Config > Workspace > [your workspace] under Environments.
Evaluate a guard
client.IsOpen(ctx, guardName) reads from the locally cached bundle. No network call occurs per check.
if client.IsOpen(ctx, "payments.checkout") {
// guarded code path
}Passing properties
Attach a properties map to the context using liteguard.AddProperties. Any call to IsOpen in the same request can then be evaluated against those properties:
func handleCheckout(w http.ResponseWriter, r *http.Request) {
ctx := liteguard.AddProperties(r.Context(), map[string]any{
"user_id": userID,
"plan": plan,
})
if client.IsOpen(ctx, "payments.checkout") {
// guarded code path
}
}Properties attached to the context are merged into the evaluation scope. Call AddProperties again to extend or override the current set.
Scopes
For finer control, create an explicit scope with a fixed set of properties:
scope := client.CreateScope(map[string]any{
"user_id": userID,
"plan": plan,
})
if scope.IsOpen(ctx, "payments.checkout") {
pass
}
if scope.IsOpen(ctx, "billing.invoice_download") {
pass
}Scopes do not read from the context properties, so they give a predictable, isolated evaluation surface.
Detailed decisions
Use client.Evaluate when you need the full decision object, such as a rate limit remaining count or the rule that matched:
decision, err := client.Evaluate(ctx, "payments.checkout")
if err != nil {
// handle
}
if decision.IsOpen {
// guarded code path
}Shut down cleanly
Shutdown() flushes buffered telemetry and stops background goroutines:
defer client.Shutdown()Pair Shutdown with a signal handler for long-lived servers:
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT)
go func() {
<-sigs
client.Shutdown()
os.Exit(0)
}()Verify in Liteguard
After calling IsOpen at least once, open the Guards tab and confirm your guard appears. See Your First Guard to configure its behavior.