SDK Reference

Go

Lightweight Go SDK with generics (Go 1.21+), context-based operations, goroutine-safe evaluation, and background polling.

Installation

bash
go get github.com/toggleai/go-sdk

Basic Usage

The Go SDK is engineered for high-concurrency microservices and cloud-native backends, delivering extreme speed and zero-dependency efficiency in parallel goroutine runtimes:

⚡ Local In-Memory Evaluation

When client.Init() is called, the SDK makes a single secure HTTP request to GET /sdk/config to retrieve the configuration rules. Subsequent checks via client.GetFlag() or typed helpers like GetFlagValue() execute instantly in-memory under sub-millisecond latencies—completely bypassing network overhead from your hot API request paths.

🛰️ Edge Remote Evaluation

For highly sensitive computations or real-time rules that must bypass local client-side caches, client.EvaluateFlagRemote() makes a direct network call to the edge gateway endpoint POST /sdk/evaluate, returning fresh determinations immediately.

main.go
package main

import (
    "context"
    "fmt"
    "log"

    toggleai "github.com/toggleai/go-sdk"
)

func main() {
    client, err := toggleai.NewClient(toggleai.Options{
        ClientID:          "pk_live_xxx",
        Secret:            "sk_live_xxx",
        PollingIntervalMs: 30000,
        DefaultContext: &toggleai.EvaluationContext{
            Attributes: map[string]interface{}{
                "server_region": "us-east-1",
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Initialize (fetches config, starts polling)
    if err := client.Init(context.Background()); err != nil {
        log.Fatal(err)
    }

    // Evaluate a flag
    ctx := &toggleai.EvaluationContext{
        UserID: "user_123",
        Attributes: map[string]interface{}{
            "plan":    "premium",
            "country": "US",
        },
    }

    result, err := client.GetFlag("new-checkout", ctx)
    if err != nil {
        log.Printf("Flag error: %v", err)
    } else {
        fmt.Printf("Flag: %s, Enabled: %v, Reason: %s\n",
            result.Key, result.Enabled, result.Reason)
    }
}

Typed Access with Generics

The Go SDK uses Go generics for type-safe flag values and config access. These are package-level functions (not methods) due to Go's method constraints on generics.

go
// Typed flag values
color := toggleai.GetFlagValue(client, "button-color", ctx, "#000000")
maxItems := toggleai.GetFlagValue(client, "max-items", ctx, 10)
ratio := toggleai.GetFlagValue(client, "split-ratio", ctx, 0.5)

// Typed config values
timeout := toggleai.GetConfig(client, "api_timeout_ms", 5000)
apiUrl := toggleai.GetConfig(client, "api_base_url", "https://api.example.com")

// Complex types (unmarshalled from JSON)
type ThemeConfig struct {
    Primary   string `json:"primary"`
    Secondary string `json:"secondary"`
}
theme := toggleai.GetConfig(client, "theme_colors", ThemeConfig{
    Primary: "#ffffff",
})

Goroutine Safety

The client is fully goroutine-safe. The config payload is protected by a sync.RWMutex, and the polling goroutine runs independently.

go
// Safe to call from multiple goroutines concurrently
func handleRequest(w http.ResponseWriter, r *http.Request) {
    userId := r.Header.Get("X-User-ID")
    ctx := &toggleai.EvaluationContext{UserID: userId}

    result, _ := client.GetFlag("feature-x", ctx)
    if result.Enabled {
        // serve new experience
    }
}

// Use with net/http
http.HandleFunc("/api/data", handleRequest)
log.Fatal(http.ListenAndServe(":8080", nil))

Logging & Errors

go
logger := client.GetLogger()

logger.Info("User signed in", map[string]interface{}{
    "userId":    "user_123",
    "sessionId": "sess_abc",
})

logger.Warn("Slow query", map[string]interface{}{
    "duration_ms": 450,
    "query":       "SELECT ...",
})

// Capture errors
if err != nil {
    logger.CaptureError(err, map[string]interface{}{
        "endpoint": "/api/checkout",
    })
}

// Flush before shutdown
logger.Flush(context.Background())

Error Handling

go
import toggleai "github.com/toggleai/go-sdk"

client, err := toggleai.NewClient(opts)
if err != nil {
    var sdkErr *toggleai.SDKError
    if errors.As(err, &sdkErr) {
        switch sdkErr.Code {
        case toggleai.ErrInvalidKey:
            log.Fatal("Invalid API key credentials")
        case toggleai.ErrNetworkError:
            log.Fatal("Cannot reach ToggleAI API")
        case toggleai.ErrRateLimited:
            log.Fatal("Rate limited")
        }
    }
}

Configuration Options

FieldTypeDefault
ClientIDstringrequired
Secretstringrequired
PollingIntervalMsint30000
EvaluationModeEvaluationMode"local"
DisableCacheboolfalse
DefaultContext*EvaluationContextnil
TimeoutMsint10000

API Reference

Function / MethodReturns
NewClient(opts)(*Client, error)
client.Init(ctx)error
client.Close()
client.GetFlag(key, ctx)(FlagEvaluationResult, error)
GetFlagValue[T](client, key, ctx, default)T
GetConfig[T](client, key, default)T
client.GetLogger()*Logger
logger.Info(msg, ctx)
logger.Warn(msg, ctx)
logger.Error(msg, ctx)
logger.CaptureError(err, ctx)
logger.Flush(ctx)