---
title: "Go SDK"
---

# Go SDK

**Recommended:** `github.com/jackc/pgx/v5` (direct PG wire) **or** `github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go` (REST API client)
**Repo:** [heliosdb-sdks](https://github.com/HeliosDatabase/HeliosDB-SDKs)
**Compatible with:** all HeliosDB editions (Nano, Lite, Full)

---

## UVP

There is no in-process Go embedding API for HeliosDB Nano — the engine is Rust. That's by design: the Nano binary speaks the **PostgreSQL v3 wire protocol** natively, so the standard Go PostgreSQL drivers (`pgx`, `lib/pq`, `database/sql`, GORM, ent) connect without adapters. For services that prefer HTTP, the HeliosDB Go client (`sdks/go` in HeliosDB-SDKs) wraps the REST API: SQL, branches, vector stores and agent memory. No CGo or FFI is involved.

---

## Path A — Direct PG Wire (`pgx`)

The first-choice path for Go services. Widely used driver, prepared statements, connection pooling, full SQL surface.

### Install

```bash
go get github.com/jackc/pgx/v5@latest
```

### Connect

```go
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/jackc/pgx/v5"
)

const dsn = "postgresql://postgres:s3cret@127.0.0.1:5432/postgres"

func main() {
    ctx := context.Background()
    conn, err := pgx.Connect(ctx, dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close(ctx)

    var v string
    if err := conn.QueryRow(ctx, "SELECT version()").Scan(&v); err != nil {
        log.Fatal(err)
    }
    fmt.Println(v)
}
```

### CRUD

```go
type Product struct {
    ID    int
    Name  string
    Price float64
}

// Schema (one-time)
_, err := conn.Exec(ctx, `
    CREATE TABLE IF NOT EXISTS products (
        id    SERIAL PRIMARY KEY,
        name  TEXT NOT NULL,
        price NUMERIC(10, 2)
    )`)

// Insert
var id int
err = conn.QueryRow(ctx,
    `INSERT INTO products (name, price) VALUES ($1, $2) RETURNING id`,
    "Widget", 9.99,
).Scan(&id)

// Read
rows, err := conn.Query(ctx,
    `SELECT id, name, price FROM products WHERE price < $1 ORDER BY id`, 50.0)
defer rows.Close()
for rows.Next() {
    var p Product
    rows.Scan(&p.ID, &p.Name, &p.Price)
    fmt.Println(p)
}

// Update
_, err = conn.Exec(ctx, `UPDATE products SET price = $1 WHERE id = $2`, 12.99, id)

// Delete
_, err = conn.Exec(ctx, `DELETE FROM products WHERE id = $1`, id)
```

### Connection Pool

For HTTP services use `pgxpool`:

```go
import "github.com/jackc/pgx/v5/pgxpool"

pool, err := pgxpool.New(ctx, dsn)
defer pool.Close()

// Use pool.Query / pool.Exec / pool.QueryRow exactly like *pgx.Conn
```

### Transactions

```go
tx, _ := conn.Begin(ctx)
defer tx.Rollback(ctx)        // no-op if Commit succeeds

_, err = tx.Exec(ctx, "UPDATE accounts SET balance = balance - $1 WHERE id = $2", 100, fromID)
if err != nil { return err }
_, err = tx.Exec(ctx, "UPDATE accounts SET balance = balance + $1 WHERE id = $2", 100, toID)
if err != nil { return err }

return tx.Commit(ctx)
```

### Vector Search

`VECTOR(n)` accepts the standard text literal `'[v1,v2,...]'` over the wire; we marshal `[]float32` to that form:

```go
import (
    "strconv"
    "strings"
)

func vecLit(v []float32) string {
    parts := make([]string, len(v))
    for i, f := range v {
        parts[i] = strconv.FormatFloat(float64(f), 'f', 6, 32)
    }
    return "[" + strings.Join(parts, ",") + "]"
}

// Schema
conn.Exec(ctx, `
    CREATE TABLE IF NOT EXISTS docs (
        id SERIAL PRIMARY KEY,
        title TEXT,
        embedding VECTOR(384)
    );
    CREATE INDEX IF NOT EXISTS docs_emb_idx
        ON docs USING hnsw (embedding vector_cosine_ops);`)

// Insert
emb := make([]float32, 384)  // populate from your embedder
conn.Exec(ctx,
    `INSERT INTO docs (title, embedding) VALUES ($1, $2::vector)`,
    "Helios release", vecLit(emb))

// k-NN
qVec := make([]float32, 384)  // query vector
rows, _ := conn.Query(ctx,
    `SELECT id, title, embedding <=> $1::vector AS distance
     FROM docs ORDER BY distance LIMIT $2`,
    vecLit(qVec), 10)
defer rows.Close()
for rows.Next() {
    var id int
    var title string
    var dist float64
    rows.Scan(&id, &title, &dist)
    fmt.Printf("%.4f  %s\n", dist, title)
}
```

Distance operators:

| Operator | Distance | Use case |
|---------:|----------|----------|
| `<=>` | Cosine | Normalized text/sentence embeddings |
| `<->` | L2 | Image / unnormalized vectors |
| `<#>` | Negative inner product | Already-normalized, speed-critical |

### `database/sql` (standard library)

If you prefer the stdlib interface, pgx ships a stdlib adapter:

```go
import (
    "database/sql"
    _ "github.com/jackc/pgx/v5/stdlib"
)

db, _ := sql.Open("pgx", dsn)
defer db.Close()

rows, _ := db.QueryContext(ctx, "SELECT id, name FROM users WHERE id = $1", 42)
```

GORM and ent ride on top of `database/sql`, so they work unchanged.

---

## Path B — REST API Client (`sdks/go`)

For services that talk to Nano over HTTP. The client calls the REST API (`/v1/...`)
that `heliosdb-nano start` serves on its HTTP port (8080 by default).

### Install

```bash
go get github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go@latest
```

### Connect + Query

```go
import heliosdb "github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go"

client, err := heliosdb.NewClient("http://localhost:8080",
    heliosdb.WithAPIKey("api-key"), // only needed if the server requires a key
)
if err != nil {
    log.Fatal(err)
}

res, err := client.Query(ctx, "SELECT id, title FROM posts WHERE author = $1", "alice@example.com")
if err != nil {
    log.Fatal(err)
}
for _, row := range res.Rows {
    fmt.Println(row["id"], row["title"])
}

// Statements that don't return rows
n, err := client.Exec(ctx, "UPDATE posts SET body = $1 WHERE id = $2", "edited", 1)
```

### Branches

```go
branches, err := client.ListBranches(ctx)
dev, err := client.CreateBranch(ctx, "dev", "main")
res, err := client.QueryOnBranch(ctx, "dev", "SELECT count(*) FROM posts")
```

### Vector Search

```go
hits, err := client.VectorSearchByVector(ctx, "docs", queryVec,
    heliosdb.WithTopK(10),
    heliosdb.WithFilter(map[string]interface{}{"category": "tech"}),
)
for _, hit := range hits {
    fmt.Println(hit.ID, hit.Score, hit.Metadata["title"])
}
```

### Agent Memory

```go
mem := client.Memory("session-42")
_ = mem.Add(ctx, "user", "What's our refund policy?")
history, _ := mem.Get(ctx, 20)
```

Errors from non-2xx responses come back as `*heliosdb.APIError` (`StatusCode`, `Message`).
The Go client does not wrap the auth or realtime endpoints — call those REST
endpoints directly (see the BaaS REST tutorial below) or use the TypeScript SDK.

---

## When to Pick Which

| Need | Use |
|------|-----|
| Backend service, heavy SQL | Path A (`pgx`) |
| GORM / ent / sqlx | Path A |
| Bulk imports (`COPY FROM`) | Path A |
| SQL over HTTP, branches, vector stores, agent memory | Path B |
| JWT auth flows, WebSocket realtime subscriptions | REST endpoints directly, or the TypeScript SDK |

Both paths can share the same Nano server; data written via `pgx` is immediately visible through the REST API and vice versa.

---

## Next Steps

- [GO_EMBEDDED_APP](https://www.heliosdb.com/docs/nano/guides/tutorials/sdk/go_embedded_app/) — full Go service, end-to-end CRUD + vector search via pgx.
- [BAAS_REST_API_TUTORIAL](https://www.heliosdb.com/docs/nano/guides/tutorials/baas_rest_api_tutorial/) — REST endpoints at the curl level.
- [VECTOR_SEARCH_TUTORIAL](https://www.heliosdb.com/docs/nano/guides/tutorials/vector_search_tutorial/) — distance metrics, HNSW tuning.
- [Python SDK](https://www.heliosdb.com/docs/nano/api/python-sdk/) / [TypeScript SDK](https://www.heliosdb.com/docs/nano/api/typescript-sdk/) — same patterns in other languages.
