> ## Documentation Index
> Fetch the complete documentation index at: https://docs.varianz.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Go SDK

> Instrument Go services with varianz.VPoint and service registration: typed wrappers, field naming, sessions via context.Context, and varianz-gen codegen.

The Go application SDK is module `go.varianz.io/sdk`, imported as `go.varianz.io/sdk/varianz` ([install](/installation#go)). The test-side package `varianztest` is covered in [Testing → Go](/testing/go).

```go theme={null}
import "go.varianz.io/sdk/varianz"

var vz = varianz.New(varianz.WithEndpoint("http://localhost:50051"))

func main() {
    if err := vz.Init(); err != nil { log.Fatal(err) }
    defer vz.Close()
    // ...
}
```

`vz.Init()` and `defer vz.Close()` in `main()` are required — without `Init()`, VPoints don't connect to the registry. When the SDK is [disabled](/reference/configuration), `varianz.VPoint` returns your original function unchanged and every registration call succeeds as a no-op.

## Defining VPoints

`varianz.VPoint` is a typed higher-order wrapper: it registers the function and returns a callable with the same signature.

```go theme={null}
type PricingRequest struct {
    BasePrice float64
    Quantity  int
}
type PricingResponse struct {
    Total float64
}

var CalculatePrice = varianz.VPoint(vz, "pricing/calculate-price",
    func(ctx context.Context, req PricingRequest) (PricingResponse, error) {
        return PricingResponse{Total: req.BasePrice * float64(req.Quantity)}, nil
    },
)
```

Rules:

* The signature is `func(context.Context, Req) (Resp, error)` — exactly one input parameter besides the context. Group multiple arguments into a struct.
* `Req`/`Resp` can be structs, primitives, or proto messages (pointer types included).
* Use struct type names directly in CEL (`PricingResponse`, not `pb.PricingResponse`). Nested proto messages construct fine in CEL literals — no flattening needed.

### Where to declare

Three equivalent patterns — there is no rule that VPoints must be package-level:

1. **Package-level `var`** (above) — simplest for standalone functions.
2. **Service struct + `vz.Register`** — most idiomatic for dependency-injected services:

   ```go theme={null}
   type PricingService struct {
       varianz.Embed `varianz:"pricing"`
       DB            *sql.DB
   }

   func (s *PricingService) CalculatePrice(ctx context.Context, req PricingRequest) (PricingResponse, error) { ... }

   proxy := vz.Register(&PricingService{DB: db})
   result, err := proxy.Call(ctx, "CalculatePrice", req)
   ```

   Every exported method becomes a VPoint, named PascalCase → kebab-case with the `varianz` tag as prefix (`CalculatePrice` → `pricing/calculate-price`; acronyms group: `HTTPSPort` → `https-port`).
3. **Wrap a bound method** — `varianz.VPoint(vz, name, svc.CalculatePrice)` when you want a typed package-level callable that still captures instance state.

With [`varianz-gen`](/guides/build-integration#go) you get typed proxies instead of `proxy.Call`'s `any` returns.

## Sessions

The session rides on `context.Context`:

```go theme={null}
ctx = varianz.WithSession(ctx, sessionID)   // set (in your server interceptor)
sid := varianz.SessionFromContext(ctx)      // read (for outbound injection)
```

Both `varianz.VPoint` callables and `proxy.Call` extract it automatically. Interceptor and middleware snippets: [Propagate sessions](/guides/propagate-sessions#go). Never start a goroutine without passing the parent context.

## Field names

Schema field names resolve in priority order:

1. `varianz:"name"` tag — explicit override
2. `protobuf` tag — proto canonical name
3. `json:"name"` tag — covers oapi-codegen, sqlc, gqlgen, and similar codegen output
4. `toSnakeCase(GoName)` — untagged fallback (`BasePrice` → `base_price`)

```go theme={null}
type Order struct {
    ID       string  `varianz:"order_id"`     // explicit
    Amount   float64                          // auto: "amount"
    Internal string  `varianz:"-"`            // excluded from the schema
    Note     string  `varianz:"note,opaque"`  // passes through, hidden from CEL
}
```

Registration validates struct types and fails with a clear error for structs with no exported fields or fields of type `chan`, `func`, or `unsafe.Pointer`. Proto-internal fields (`state`, `sizeCache`, `unknownFields`) are skipped automatically.

## Context functions

```go theme={null}
vz.Function("applyTax", func(price, rate float64) float64 {
    return price * (1.0 + rate)
}, varianz.WithFunctionParams("price", "rate"))

// Scoped to VPoints with a matching profile:
vz.Function("clampFloat", clamp,
    varianz.WithFunctionParams("value", "lo", "hi"),
    varianz.WithFunctionProfile("pricing"))
```

Available in CEL as `ctx.applyTax(...)`.

## Troubleshooting

* **`go test -tags=integration` fails with vet errors in upstream code** — the integration tag pulls files into the build that surface pre-existing `go vet` warnings (commonly `status.Errorf(codes.Internal, err.Error())`). Fix upstream with an explicit `"%s"`, or run with `-vet=off`.
* **Vendored builds drop the SDK** — `-mod=vendor` needs both `vendor/go.varianz.io/sdk/` and the `vendor/modules.txt` entry. Re-run `go mod vendor` after upgrading; don't hand-copy.
* **Link errors or missing symbols in Docker** — you built with `CGO_ENABLED=0` or a `static`/`scratch` runtime image. See the [Docker pattern](/installation#go).
