Go SDK

The official NoLag SDK for Go. Idiomatic Go client with goroutines and channels support.

Installation

go get github.com/NoLagApp/nolag-go

Quick Start

package main

import (
    "fmt"
    "time"

    nolag "github.com/NoLagApp/nolag-go"
)

func main() {
    // Create client with your actor token
    client := nolag.New("your-actor-token")

    // Connect to NoLag
    if err := client.Connect(); err != nil {
        panic(err)
    }
    defer client.Close()

    // Subscribe to a topic
    client.Subscribe("my-topic", func(data any, meta nolag.MessageMeta) {
        fmt.Printf("Received: %v\n", data)
    })

    // Publish a message
    client.Emit("my-topic", map[string]any{"hello": "world"})

    // Keep running
    time.Sleep(60 * time.Second)
}

Configuration

import (
    "time"
    nolag "github.com/NoLagApp/nolag-go"
)

options := nolag.Options{
    URL:                  "wss://broker.nolag.app/ws", // Custom broker URL
    Reconnect:            true,                         // Auto-reconnect
    ReconnectInterval:    5 * time.Second,              // Reconnect interval
    MaxReconnectAttempts: 10,                           // Max attempts (0 = infinite)
    HeartbeatInterval:    30 * time.Second,             // Heartbeat interval (0 to disable)
    QoS:                  nolag.QoSAtLeastOnce,         // Default QoS
    Debug:                true,                         // Enable debug logging
}

client := nolag.New("your-actor-token", options)

Subscribing to Topics

// Basic subscription
client.Subscribe("chat/messages", func(data any, meta nolag.MessageMeta) {
    fmt.Printf("Message from %s: %v\n", meta.Sender, data)
})

// With options
qos := nolag.QoSExactlyOnce
loadBalance := true
client.Subscribe("tasks", handler, nolag.SubscribeOptions{
    QoS:              &qos,
    LoadBalance:      &loadBalance,
    LoadBalanceGroup: "workers",
})

// Unsubscribe
client.Unsubscribe("chat/messages")

Publishing Messages

// Publish any data (maps, structs, strings, etc.)
client.Emit("chat/messages", map[string]any{"text": "Hello!"})

// With options
qos := nolag.QoSExactlyOnce
client.Emit("status", map[string]any{"online": true}, nolag.EmitOptions{
    QoS:    &qos,
    Retain: true, // Retain last message for new subscribers
})

Connection Events

// Listen for connection events
client.On("connected", func(args ...any) {
    fmt.Println("Connected!")
})

client.On("disconnected", func(args ...any) {
    fmt.Println("Disconnected")
})

client.On("reconnecting", func(args ...any) {
    attempt := args[0].(int)
    fmt.Printf("Reconnecting... attempt %d\n", attempt)
})

client.On("error", func(args ...any) {
    err := args[0].(error)
    fmt.Printf("Error: %v\n", err)
})

// Check connection status
if client.Status() == nolag.StatusConnected {
    fmt.Println("We're connected!")
}

Presence

// Set your presence data
client.SetPresence(map[string]any{
    "status": "online",
    "typing": false,
})

// Get presence of all actors in a topic
presenceList, err := client.GetPresence("chat/room-1")
if err == nil {
    for _, actor := range presenceList {
        fmt.Printf("%s: %v\n", actor.ActorTokenID, actor.Presence)
    }
}

// Listen for presence changes
client.On("presence", func(args ...any) {
    topic := args[0].(string)
    presence := args[1]
    fmt.Printf("Presence update in %s: %v\n", topic, presence)
})

Error Handling

package main

import (
    "fmt"
    nolag "github.com/NoLagApp/nolag-go"
)

func main() {
    client := nolag.New("your-actor-token")

    // Handle errors via event
    client.On("error", func(args ...any) {
        if err, ok := args[0].(error); ok {
            fmt.Printf("Error: %v\n", err)
        }
    })

    // Connect with error handling
    if err := client.Connect(); err != nil {
        fmt.Printf("Connection failed: %v\n", err)
        return
    }
    defer client.Close()

    // Operations return errors
    if err := client.Emit("topic", "data"); err != nil {
        fmt.Printf("Emit failed: %v\n", err)
    }
}

QoS Levels

LevelConstantDescription
0QoSAtMostOnceFire and forget, no acknowledgment
1QoSAtLeastOnceGuaranteed delivery, may have duplicates
2QoSExactlyOnceGuaranteed exactly one delivery

REST API Client

The SDK also includes a REST API client for managing apps, rooms, and actors:

package main

import (
    "context"
    "fmt"

    nolag "github.com/NoLagApp/nolag-go"
)

func main() {
    ctx := context.Background()

    // Create API client with project-scoped API key
    api := nolag.NewAPI("nlg_live_xxx.secret")

    // List all apps in your project
    apps, err := api.Apps.List(ctx, nil)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Found %d apps\n", len(apps.Data))

    // Create a new app
    app, err := api.Apps.Create(ctx, nolag.AppCreate{
        Name:        "my-chat-app",
        Description: "A real-time chat application",
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("Created app: %s\n", app.AppID)

    // Create a room in the app
    room, err := api.Rooms.Create(ctx, app.AppID, nolag.RoomCreate{
        Name: "general",
        Slug: "general",
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("Created room: %s\n", room.RoomID)

    // Create an actor (save the access token!)
    actor, err := api.Actors.Create(ctx, nolag.ActorCreate{
        Name:      "web-client",
        ActorType: nolag.ActorDevice,
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("Actor token: %s\n", actor.AccessToken)
}

Load Balancing

Distribute messages across multiple subscribers:

loadBalance := true
client.Subscribe("tasks", processTask, nolag.SubscribeOptions{
    LoadBalance:      &loadBalance,
    LoadBalanceGroup: "task-workers",
})

Type Definitions

import nolag "github.com/NoLagApp/nolag-go"

// WebSocket Client
nolag.Client           // The client
nolag.Options          // Connection options
nolag.SubscribeOptions // Subscription options
nolag.EmitOptions      // Publish options

// Enums
nolag.ConnectionStatus // StatusDisconnected, StatusConnecting, etc.
nolag.ActorType        // ActorDevice, ActorUser, ActorServer
nolag.QoS              // QoSAtMostOnce, QoSAtLeastOnce, QoSExactlyOnce

// Data types
nolag.MessageMeta      // Message metadata (Sender, Timestamp)
nolag.ActorPresence    // Presence info
nolag.MessageHandler   // func(data any, meta MessageMeta)
nolag.EventHandler     // func(args ...any)

// REST API Client
nolag.API              // REST API client
nolag.APIOptions       // API client options
nolag.NoLagAPIError    // API error type

// Resources
nolag.AppResource, nolag.AppCreate, nolag.AppUpdate
nolag.RoomResource, nolag.RoomCreate, nolag.RoomUpdate
nolag.ActorResource, nolag.ActorWithToken, nolag.ActorCreate, nolag.ActorUpdate

Requirements

  • Go 1.21+
  • github.com/gorilla/websocket v1.5.1
  • github.com/vmihailenco/msgpack/v5 v5.4.1

Next Steps