Go SDK

Lightweight WebSocket client for Go services and CLIs.

Installation

go get github.com/raucheacho/konet/sdk/go

Quick Start

package main
 
import (
    "context"
    "log"
 
    konet "github.com/raucheacho/konet/sdk/go"
)
 
func main() {
    ctx := context.Background()
 
    client := konet.New("ws://localhost:4000/socket", "<anon_key>")
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect()
 
    ch := client.Channel("room:lobby")
    if err := ch.Subscribe(ctx); err != nil {
        log.Fatal(err)
    }
 
    ch.On("message", func(payload interface{}) {
        log.Printf("recv: %+v\n", payload)
    })
 
    ch.Send("message", map[string]any{"text": "Hello from Go!"})
 
    select {} // block
}

API

// Client — New builds the client; Connect opens the socket.
c := konet.New(url, token)              // optional konet.ClientOptions
c := konet.New(url, token, konet.ClientOptions{
    HeartbeatInterval: 30 * time.Second,
    ReconnectDelay:    time.Second,
    MaxReconnectTries: 10,
    HTTPHeader:        nil, // extra headers for the WS handshake
})
err := c.Connect(ctx)
c.Disconnect()
 
// Channel
ch := c.Channel("room:lobby")
err := ch.Subscribe(ctx)                 // blocks until the join is confirmed
err := ch.Send(event string, payload interface{})
off := ch.On(event string, handler func(payload interface{})) // off() removes it
err := ch.Unsubscribe()
 
// Decoding payloads into a struct
var msg MyType
err := konet.MarshalPayload(payload, &msg)

Presence tracking is currently available in the JavaScript SDK only.

Binary Frames & Floor Control

For anything at a media rate. Take the floor before sending — a binary frame without it is refused. See the protocol page for the guarantees.

channel := client.Channel("room:team-42:ptt")
if err := channel.Subscribe(ctx); err != nil {
    return err
}
 
channel.OnBinary("a", func(data []byte) {
    // an incoming frame; the slice is only valid for this call
})
 
holder, err := channel.AcquireFloor(ctx)
if err != nil {
    // someone else is talking; the error names them
    return err
}
_ = holder
 
if err := channel.SendBinary("a", frame); err != nil {
    return err
}
 
return channel.ReleaseFloor(ctx)

SendBinary copies its argument, so a caller may reuse one buffer for every frame.

Binary handlers run synchronously, unlike On handlers which each get a goroutine: audio frames have to reach a play-out buffer in the order they arrived, and one goroutine per frame would not promise that.