Skip to content

Go

Preview

Guide to using Soxom-generated Go SDKs. The Go target aims to deliver idiomatic Go (functional options, context.Context on every call, iterator pagination, typed errors). The sections below describe the target surface; not every feature is fully delivered yet, and parity with the TypeScript, Python, and Java generators will arrive incrementally.

soxom.yaml
targets:
go:
module: github.com/acme/sdk-go
OptionDefaultDescription
module-Go module path (required)
Terminal window
go get github.com/acme/sdk-go
package main
import (
"context"
"os"
acme "github.com/acme/sdk-go"
)
func main() {
// With token
client := acme.NewClient(
acme.WithToken(os.Getenv("ACME_API_TOKEN")),
)
// With options
client := acme.NewClient(
acme.WithToken(os.Getenv("ACME_API_TOKEN")),
acme.WithBaseURL("https://api.acme.com/v2"),
acme.WithTimeout(30 * time.Second),
)
// From environment (if configured)
client := acme.NewClient() // Reads from ACME_API_TOKEN
}

All SDK methods require a context as the first argument:

ctx := context.Background()
// Simple request
user, err := client.Users.Get(ctx, "user-123")
// With timeout
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
user, err := client.Users.Get(ctx, "user-123")
// With cancellation
ctx, cancel := context.WithCancel(ctx)
go func() {
// Cancel after some condition
cancel()
}()
user, err := client.Users.Get(ctx, "user-123")
ctx := context.Background()
// Get
user, err := client.Users.Get(ctx, "user-123")
if err != nil {
log.Fatal(err)
}
fmt.Println(user.Name)
// Create
newUser, err := client.Users.Create(ctx, acme.UserCreate{
Email: "john@example.com",
Name: "John Doe",
})
// Update
updated, err := client.Users.Update(ctx, "user-123", acme.UserUpdate{
Name: acme.String("Jane Doe"), // Optional field helper
})
// Delete
err = client.Users.Delete(ctx, "user-123")

Go SDK uses strongly typed structs:

// Request types
req := acme.UserCreate{
Email: "john@example.com", // Required field
Name: "John Doe", // Required field
}
// Optional fields use pointers or helper functions
req := acme.UserUpdate{
Name: acme.String("New Name"), // *string
Status: acme.UserStatus("active"), // Optional enum
}
// Response types
user, _ := client.Users.Get(ctx, "user-123")
fmt.Println(user.ID) // string
fmt.Println(user.Email) // string
fmt.Println(user.Status) // acme.UserStatus
fmt.Println(user.CreatedAt) // time.Time
// Union types use interfaces
type PaymentMethod interface {
isPaymentMethod()
}
// Type switch for handling
func processPayment(method acme.PaymentMethod) {
switch m := method.(type) {
case acme.CreditCard:
fmt.Printf("Card: %s\n", m.CardNumber)
case acme.BankAccount:
fmt.Printf("Account: %s\n", m.AccountNumber)
}
}
// Iterate through all pages
iter := client.Users.List(ctx)
for iter.Next() {
user := iter.Current()
fmt.Println(user.Name)
}
if err := iter.Err(); err != nil {
log.Fatal(err)
}
// With options
iter := client.Users.List(ctx, acme.ListUsersParams{
Status: acme.String("active"),
Limit: acme.Int(50),
})
// Get first page
page, err := client.Users.ListPage(ctx, acme.ListUsersParams{
Limit: acme.Int(10),
})
if err != nil {
log.Fatal(err)
}
for _, user := range page.Data {
fmt.Println(user.Name)
}
// Get next page
if page.HasMore {
nextPage, err := client.Users.ListPage(ctx, acme.ListUsersParams{
After: page.NextCursor,
Limit: acme.Int(10),
})
}
// SSE streaming
stream, err := client.Chat.Completions.Create(ctx, acme.ChatCompletionRequest{
Model: "gpt-4",
Messages: []acme.ChatMessage{
{Role: "user", Content: "Hello"},
},
Stream: true,
})
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for stream.Next() {
chunk := stream.Current()
if content := chunk.Choices[0].Delta.Content; content != "" {
fmt.Print(content)
}
}
if err := stream.Err(); err != nil {
log.Fatal(err)
}
import "errors"
user, err := client.Users.Get(ctx, "user-123")
if err != nil {
var apiErr *acme.APIError
if errors.As(err, &apiErr) {
switch apiErr.StatusCode {
case 401:
fmt.Println("Authentication failed")
case 404:
fmt.Println("User not found")
case 429:
fmt.Printf("Rate limited. Retry after %d seconds\n", apiErr.RetryAfter)
default:
fmt.Printf("API error: %d - %s\n", apiErr.StatusCode, apiErr.Message)
}
return
}
// Network or other errors
log.Fatal(err)
}
// Check specific error types
var notFoundErr *acme.NotFoundError
if errors.As(err, &notFoundErr) {
fmt.Println("Resource not found:", notFoundErr.Resource)
}
var rateLimitErr *acme.RateLimitError
if errors.As(err, &rateLimitErr) {
time.Sleep(time.Duration(rateLimitErr.RetryAfter) * time.Second)
// Retry...
}
var validationErr *acme.ValidationError
if errors.As(err, &validationErr) {
for _, e := range validationErr.Errors {
fmt.Printf("Field %s: %s\n", e.Field, e.Message)
}
}

Override settings per-request using functional options:

// Custom timeout
report, err := client.Reports.Generate(ctx, params,
acme.WithRequestTimeout(2 * time.Minute),
)
// Disable retries
payment, err := client.Payments.Create(ctx, data,
acme.WithRetries(acme.RetryConfig{Enabled: false}),
)
// Custom headers
result, err := client.Users.List(ctx,
acme.WithHeader("X-Custom-Header", "value"),
)
// Idempotency key
order, err := client.Orders.Create(ctx, data,
acme.WithIdempotencyKey("unique-request-123"),
)

Go SDK follows Go naming conventions:

OpenAPIGo
user_nameUserName
created_atCreatedAt
api_keyAPIKey
list methodList
get methodGet
github.com/acme/sdk-go/
├── client.go # Client type
├── options.go # Client options
├── users.go # Users resource
├── orders.go # Orders resource
├── types.go # Shared types
├── errors.go # Error types
├── go.mod
├── go.sum
└── README.md