go-sdk

star 0

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.

MasonEgger By MasonEgger schedule Updated 1/27/2026

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.Context as 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.Context as 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 of time.Now()
  • workflow.Sleep(ctx, d) instead of time.Sleep()
  • workflow.Go(ctx, fn) instead of go fn()
  • workflow.Channel instead of Go channels
  • workflow.Selector instead of select

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

  1. Using go keyword in workflows - Use workflow.Go() instead
  2. Using Go channels - Use workflow.Channel instead
  3. Iterating over maps - Order is non-deterministic, sort keys first
  4. Using time.Now() - Use workflow.Now(ctx) instead
  5. Missing activity registration - Must register all activities on worker
  6. Using fmt.Println() in workflows - Use workflow.GetLogger() instead

Additional Resources

Reference Files

  • references/determinism.md - Safe alternatives, workflowcheck, concurrency patterns, history replay
  • references/error-handling.md - ApplicationError, retry policies, error handling, idempotency
  • references/testing.md - TestWorkflowEnvironment, mocking, assertions
  • references/patterns.md - Selectors, signals, queries, child workflows
  • references/observability.md - Logging, metrics, tracing, Search Attributes
  • references/advanced-features.md - Continue-as-new, schedules, updates, interceptors
  • references/data-handling.md - Data converters, protobuf, payload encryption
  • references/versioning.md - GetVersion API, workflow type versioning, Worker Versioning
Install via CLI
npx skills add https://github.com/MasonEgger/temporal-plugin-claude-code --skill go-sdk
Repository Details
star Stars 0
call_split Forks 2
navigation Branch main
article Path SKILL.md
More from Creator