Skip to content

Instantly share code, notes, and snippets.

@AndyMoreland
Created January 7, 2026 18:35
Show Gist options
  • Select an option

  • Save AndyMoreland/48bac13b270ec5adb00c0bc033b9739b to your computer and use it in GitHub Desktop.

Select an option

Save AndyMoreland/48bac13b270ec5adb00c0bc033b9739b to your computer and use it in GitHub Desktop.
Golang examples for querying Chalk with multiple input namespaces (user.id and account.id)
package main
import (
"context"
"fmt"
"log"
"github.com/chalk-ai/chalk-go"
)
// User represents the user feature namespace
type User struct {
Id *int64
}
// Account represents the account feature namespace
type Account struct {
Id *int64
}
// MultiNamespaceResult combines features from multiple namespaces
type MultiNamespaceResult struct {
User User
Account Account
}
func main() {
// Initialize the Chalk gRPC client
// By default, this will use environment variables or ~/.chalk.yml configuration:
// - CHALK_CLIENT_ID or config file
// - CHALK_CLIENT_SECRET or config file
// - CHALK_API_SERVER or config file
// - CHALK_ACTIVE_ENVIRONMENT or config file
ctx := context.Background()
chalkClient, err := chalk.NewGRPCClient(ctx)
if err != nil {
log.Fatalf("Failed to create Chalk client: %v", err)
}
// Alternatively, you can explicitly configure the client:
// chalkClient, err := chalk.NewGRPCClient(
// ctx,
// &chalk.GRPCClientConfig{
// ClientId: "your-client-id",
// ClientSecret: "your-client-secret",
// ApiServer: "https://api.chalk.ai",
// EnvironmentId: "your-environment-id",
// },
// )
// if err != nil {
// log.Fatalf("Failed to create Chalk client: %v", err)
// }
// Execute an online query with multiple input namespaces
// This example queries features from both user and account namespaces
// Note: OnlineQueryBulk is used with single-element slices for a single query
res, err := chalkClient.OnlineQueryBulk(
ctx,
chalk.OnlineQueryParams{
QueryName: "multi_namespace_example",
CorrelationId: "multi-ns-123",
IncludeMeta: true,
}.
// Provide inputs from multiple namespaces
// Use slices with one element for a single query
WithInput("user.id", []string{"1"}).
WithInput("account.id", []string{"1"}).
// Request outputs from both namespaces
// Including the input features themselves
WithOutputs(
// User namespace features
"user.id",
// Account namespace features
"account.id",
),
)
if err != nil {
log.Printf("Query completed with errors: %v", err)
}
// Method 1: Unmarshal into a slice (bulk results)
var results []MultiNamespaceResult
if err := res.UnmarshalInto(&results); err != nil {
log.Fatalf("Failed to unmarshal results: %v", err)
}
// Get the first result (since we queried with one set of inputs)
if len(results) == 0 {
log.Fatal("No results returned")
}
result := results[0]
fmt.Println("=== Multi-Namespace Query Results ===")
fmt.Println("\nUser Features:")
if result.User.Id != nil {
fmt.Printf(" user.id: %d\n", *result.User.Id)
}
fmt.Println("\nAccount Features:")
if result.Account.Id != nil {
fmt.Printf(" account.id: %d\n", *result.Account.Id)
}
// Method 2: Access the Arrow table directly
fmt.Println("\n--- Accessing Arrow Table ---")
table, err := res.GetTable()
if err != nil {
log.Fatalf("Failed to get table: %v", err)
}
defer table.Release()
fmt.Printf("Number of rows: %d\n", table.NumRows())
fmt.Printf("Number of columns: %d\n", table.NumCols())
// Print column names
schema := table.Schema()
columnNames := make([]string, len(schema.Fields()))
for i, field := range schema.Fields() {
columnNames[i] = field.Name
}
fmt.Printf("Column names: %v\n", columnNames)
// Method 3: Access query metadata
if meta := res.GetQueryMeta(); meta != nil {
fmt.Printf("\n--- Query Metadata ---\n")
fmt.Printf("Query ID: %s\n", meta.QueryId)
fmt.Printf("Environment ID: %s\n", meta.EnvironmentId)
if meta.QueryTimestamp != nil {
fmt.Printf("Query Timestamp: %v\n", *meta.QueryTimestamp)
}
}
// Method 4: Check for any errors
if errors, err := res.GetErrors(); err == nil && len(errors) > 0 {
fmt.Printf("\n--- Query Errors ---\n")
for i, queryErr := range errors {
fmt.Printf("Error %d: %s\n", i+1, queryErr.Message)
fmt.Printf(" Code: %s\n", queryErr.Code)
if queryErr.Feature != "" {
fmt.Printf(" Feature: %s\n", queryErr.Feature)
}
}
}
}
package main
import (
"context"
"fmt"
"log"
"github.com/chalk-ai/chalk-go"
)
// User represents the user feature namespace
// In practice, use `chalk codegen` to generate these structs
type User struct {
Id *int64
Email *string
Name *string
CreditScore *int64
}
// Account represents the account feature namespace
// In practice, use `chalk codegen` to generate these structs
type Account struct {
Id *int64
Balance *float64
AccountType *string
IsActive *bool
}
// MultiNamespaceResult combines features from multiple namespaces
type MultiNamespaceResult struct {
User User
Account Account
}
//lint:ignore U1000 example
func multiNamespaceQuery() {
// Initialize the Chalk gRPC client
// By default, this will use environment variables or ~/.chalk.yml configuration
ctx := context.Background()
chalkClient, err := chalk.NewGRPCClient(ctx)
if err != nil {
log.Fatalf("Failed to create Chalk client: %v", err)
}
// Execute an online query with multiple input namespaces
// This example queries features from both user and account namespaces
// Note: Use OnlineQueryBulk with single-element slices for a single query
res, err := chalkClient.OnlineQueryBulk(
ctx,
chalk.OnlineQueryParams{
QueryName: "multi_namespace_example",
CorrelationId: "multi-ns-123",
IncludeMeta: true,
}.
// Provide inputs from multiple namespaces
// Use slices with one element for a single query
WithInput("user.id", []int64{1}).
WithInput("account.id", []int64{1}).
// Request outputs from both namespaces
// Including the input features themselves
WithOutputs(
// User namespace features
"user.id",
"user.email",
"user.name",
"user.credit_score",
// Account namespace features
"account.id",
"account.balance",
"account.account_type",
"account.is_active",
),
)
if err != nil {
log.Printf("Query completed with errors: %v", err)
}
// Method 1: Unmarshal into a slice (bulk results)
var results []MultiNamespaceResult
if err := res.UnmarshalInto(&results); err != nil {
log.Fatalf("Failed to unmarshal results: %v", err)
}
// Get the first result (since we queried with one set of inputs)
if len(results) == 0 {
log.Fatal("No results returned")
}
result := results[0]
fmt.Println("=== Multi-Namespace Query Results ===")
fmt.Println("\nUser Features:")
if result.User.Id != nil {
fmt.Printf(" user.id: %d\n", *result.User.Id)
}
if result.User.Email != nil {
fmt.Printf(" user.email: %s\n", *result.User.Email)
}
if result.User.Name != nil {
fmt.Printf(" user.name: %s\n", *result.User.Name)
}
if result.User.CreditScore != nil {
fmt.Printf(" user.credit_score: %d\n", *result.User.CreditScore)
}
fmt.Println("\nAccount Features:")
if result.Account.Id != nil {
fmt.Printf(" account.id: %d\n", *result.Account.Id)
}
if result.Account.Balance != nil {
fmt.Printf(" account.balance: $%.2f\n", *result.Account.Balance)
}
if result.Account.AccountType != nil {
fmt.Printf(" account.account_type: %s\n", *result.Account.AccountType)
}
if result.Account.IsActive != nil {
fmt.Printf(" account.is_active: %t\n", *result.Account.IsActive)
}
// Method 2: Access the Arrow table directly
fmt.Println("\n--- Accessing Arrow Table ---")
table, err := res.GetTable()
if err != nil {
log.Fatalf("Failed to get table: %v", err)
}
defer table.Release()
fmt.Printf("Number of rows: %d\n", table.NumRows())
fmt.Printf("Number of columns: %d\n", table.NumCols())
// Print column names
schema := table.Schema()
columnNames := make([]string, len(schema.Fields()))
for i, field := range schema.Fields() {
columnNames[i] = field.Name
}
fmt.Printf("Column names: %v\n", columnNames)
// Method 3: Access query metadata
if meta := res.GetQueryMeta(); meta != nil {
fmt.Printf("\n--- Query Metadata ---\n")
fmt.Printf("Query ID: %s\n", meta.QueryId)
fmt.Printf("Environment ID: %s\n", meta.EnvironmentId)
if meta.QueryTimestamp != nil {
fmt.Printf("Query Timestamp: %v\n", *meta.QueryTimestamp)
}
}
// Method 4: Check for any errors
if errors, err := res.GetErrors(); err == nil && len(errors) > 0 {
fmt.Printf("\n--- Query Errors ---\n")
for i, queryErr := range errors {
fmt.Printf("Error %d: %s\n", i+1, queryErr.Message)
fmt.Printf(" Code: %s\n", queryErr.Code)
if queryErr.Feature != "" {
fmt.Printf(" Feature: %s\n", queryErr.Feature)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment