name: go-sdk description: This skill should be used when the user asks to 'create a Temporal workflow in Go', 'write a Go activity', 'use go.temporal.io', 'fix Go workflow determinism', 'debug workflow replay', 'Go workflow logging', or mentions 'Temporal Go SDK'. Provides Go-specific patterns, context handling, selector usage, and observability guidance. version: 0.1.0
Temporal Go SDK Best Practices
Overview
The Temporal Go SDK provides idiomatic Go patterns for building durable workflows. Workflows and activities are regular Go functions with special context parameters. No sandbox - determinism enforced through code review and static analysis.
Quick Start
package main
import (
"context"
"time"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
"go.temporal.io/sdk/workflow"
)
func GreetActivity(ctx context.Context, name string) (string, error) {
return "Hello, " + name + "!", nil
}
func GreetingWorkflow(ctx workflow.Context, name string) (string, error) {
ao := workflow.ActivityOptions{StartToCloseTimeout: time.Minute}
ctx = workflow.WithActivityOptions(ctx, ao)
var result string
err := workflow.ExecuteActivity(ctx, GreetActivity, name).Get(ctx, &result)
return result, err
}
func main() {
c, _ := client.Dial(client.Options{})
defer c.Close()
w := worker.New(c, "greeting-queue", worker.Options{})
w.RegisterWorkflow(GreetingWorkflow)
w.RegisterActivity(GreetActivity)
w.Run(worker.InterruptCh())
}
Key Concepts
Workflow Definition
- Regular Go function with
workflow.Contextas first parameter - Returns result and error
- Use
workflow.ExecuteActivity()to call activities - Use
workflow.Go()for concurrent operations
Activity Definition
- Regular Go function with
context.Contextas first parameter - Can perform I/O, network calls, etc.
- Use
activity.GetLogger(ctx)for logging - Use
activity.RecordHeartbeat()for long operations
Worker Setup
- Create client with
client.Dial() - Create worker with
worker.New() - Register workflows and activities explicitly
Why Determinism Matters: History Replay
Temporal achieves durability through history replay. When a Worker restarts or recovers from a failure, it re-executes the Workflow code from the beginning, but instead of re-running Activities, it uses the results stored in the Event History.
This is why Workflow code must be deterministic:
- During replay, the SDK compares Commands generated by your code against the Events in history
- If the sequence differs (non-determinism), the Worker cannot restore state
- Go SDK has no sandbox - you must ensure determinism through code review and static analysis
See references/determinism.md for detailed rules and the workflowcheck tool.
Determinism Rules Summary
Safe alternatives:
workflow.Now(ctx)instead oftime.Now()workflow.Sleep(ctx, d)instead oftime.Sleep()workflow.Go(ctx, fn)instead ofgo fn()workflow.Channelinstead of Go channelsworkflow.Selectorinstead ofselect
Run the static checker:
go install go.temporal.io/sdk/contrib/tools/workflowcheck@latest
workflowcheck ./...
Replay-Aware Logging
Use workflow.GetLogger(ctx) inside Workflows for replay-safe logging that avoids duplicate messages:
func MyWorkflow(ctx workflow.Context, input string) (string, error) {
logger := workflow.GetLogger(ctx)
logger.Info("Workflow started", "input", input)
var result string
err := workflow.ExecuteActivity(ctx, MyActivity, input).Get(ctx, &result)
if err != nil {
logger.Error("Activity failed", "error", err)
return "", err
}
logger.Info("Workflow completed", "result", result)
return result, nil
}
Use activity.GetLogger(ctx) in activities for context-aware logging:
func MyActivity(ctx context.Context, input string) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("Activity started", "input", input)
// ...
return "result", nil
}
Common Pitfalls
- Using
gokeyword in workflows - Useworkflow.Go()instead - Using Go channels - Use
workflow.Channelinstead - Iterating over maps - Order is non-deterministic, sort keys first
- Using
time.Now()- Useworkflow.Now(ctx)instead - Missing activity registration - Must register all activities on worker
- Using fmt.Println() in workflows - Use
workflow.GetLogger()instead
Additional Resources
Reference Files
references/determinism.md- Safe alternatives, workflowcheck, concurrency patterns, history replayreferences/error-handling.md- ApplicationError, retry policies, error handling, idempotencyreferences/testing.md- TestWorkflowEnvironment, mocking, assertionsreferences/patterns.md- Selectors, signals, queries, child workflowsreferences/observability.md- Logging, metrics, tracing, Search Attributesreferences/advanced-features.md- Continue-as-new, schedules, updates, interceptorsreferences/data-handling.md- Data converters, protobuf, payload encryptionreferences/versioning.md- GetVersion API, workflow type versioning, Worker Versioning