Temporal Client - Go SDK
A Temporal Client enables you to communicate with the Temporal Service. Communication with a Temporal Service includes lets you perform actions such as starting Workflow Executions, sending Signals to Workflow Executions, sending Queries to Workflow Executions, getting the results of a Workflow Execution, and providing Activity Task Tokens.
This page shows you how to do the following using the Go SDK with the Temporal Client:
- Connect to a local development Temporal Service
- Connect to Temporal Cloud
- Start a Workflow Execution
- How to start a Workflow Execution
A Temporal Client cannot be initialized and used inside a Workflow. However, it is acceptable and common to use a Temporal Client inside an Activity to communicate with a Temporal Service.
Connect to development Temporal Service
Use the Dial() API available in the
go.temporal.io/sdk/client package to create a
Client. The Dial() API expects connection options such as the
Temporal Server address, the Namespace to connect to, and Transport Layer Security (TLS) configuration. You can specify
these options in the function call, or specify them using environment variables or a configuration file. We recommend
you use environment variables or a configuration file to manage these connection options securely.
When you are running a Temporal Service locally (such as the
Temporal CLI), the number of connection options you must provide is
minimal. Many SDKs default to the local host or IP address and port that Temporalite and
Docker Compose serve (127.0.0.1:7233).
If you don't provide HostPort, the Client defaults the
address and port number to 127.0.0.1:7233, which is the port of the development Temporal Service.
If you don't set a custom Namespace name in the Namespace field, the client connects to the default Namespace.
- Environment Variables
- Configuration File
- Code
Use the envconfig package to set connection options for the Temporal Client using environment variables. For a list of
all available environment variables and their default values, refer to
Environment Configuration.
For example, the following code snippet loads all environment variables and creates a Temporal Client with the options
specified in those variables. If you have defined a configuration file at either the default location
(~/.config/temporalio/temporal.toml) or a custom location specified by the TEMPORAL_CONFIG_FILE environment
variable, this will also load the default profile in the configuration file. However, any options set via environment
variables will take precedence.
package main
import (
"fmt"
"log"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)
func main() {
// Loads the "default" profile from the standard location and environment variables.
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close()
fmt.Printf("✅ Connected to Temporal namespace %q on %s\n", c.Options().Namespace, c.Options().HostPort)
}
You can use a TOML configuration file to set connection options for the Temporal Client. The configuration file lets you
configure multiple profiles, each with its own set of connection options. You can then specify which profile to use when
creating the Temporal Client. You can use the environment variable TEMPORAL_CONFIG_FILE to specify the location of the
TOML file or provide the path to the file directly in code. If you don't provide the configuration file path, the SDK
looks for it at the path ~/.config/temporalio/temporal.toml.
The connection options set in configuration files have lower precedence than environment variables. This means that if you set the same option in both the configuration file and as an environment variable, the environment variable value overrides the option set in the configuration file.
For example, the following TOML configuration file defines two profiles: default and prod. Each profile has its own
set of connection options.
# Default profile for local development
[profile.default]
address = "localhost:7233"
namespace = "default"
# Custom gRPC headers
[profile.default.grpc_meta]
my-custom-header = "development-value"
trace-id = "dev-trace-123"
# Production profile for Temporal Cloud
[profile.prod]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
api_key = "your-api-key-here"
# TLS configuration for production
[profile.prod.tls]
# TLS is auto-enabled when this TLS config or API key is present, but you can configure it explicitly
# disabled = false
# Use certificate files for mTLS
client_cert_path = "/etc/temporal/certs/client.pem"
client_key_path = "/etc/temporal/certs/client.key"
# Custom headers for production
[profile.prod.grpc_meta]
environment = "production"
service-version = "v1.2.3"
You can create a Temporal Client using a specific profile from the configuration file as follows:
package main
import (
"fmt"
"log"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)
func main() {
// Load a specific profile from the TOML config file.
// This requires a [profile.prod] section in your config.
opts, err := envconfig.LoadClientOptions(envconfig.LoadClientOptionsRequest{
ConfigFileProfile: "prod",
})
if err != nil {
log.Fatalf("Failed to load 'prod' profile: %v", err)
}
c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect using 'prod' profile: %v", err)
}
defer c.Close()
fmt.Printf("✅ Connected to Temporal namespace %q on %s using 'prod' profile\n", c.Options().Namespace, c.Options().HostPort)
}
If you don't want to use environment variables or a configuration file, you can specify connection options directly in code. This is convenient for local development and testing. You can also load a base configuration from environment variables or a configuration file, and then override specific options in code.
sample-apps/go/yourapp/gateway/main.go
package main
import (
"context"
"encoding/json"
"log"
"net/http"
"documentation-samples-go/yourapp"
"go.temporal.io/sdk/client"
)
func main() {
// Create a Temporal Client to communicate with the Temporal Cluster.
// A Temporal Client is a heavyweight object that should be created just once per process.
temporalClient, err := client.Dial(client.Options{
HostPort: client.DefaultHostPort,
})
if err != nil {
log.Fatalln("Unable to create Temporal Client", err)
}
defer temporalClient.Close()
// ...
}
Connect to Temporal Cloud
Connection to Temporal Cloud or any secured Temporal Service requires additional connection options compared to connecting to an unsecured local development instance. You can connect to Temporal Cloud using either an API key or through mTLS. You need to provide the following mandatory connection options:
- Your credentials for authentication.
- If you are using an API key, provide the API key value.
- If you are using mTLS, provide the mTLS CA certificate and mTLS private key.
- Your Namespace and Account id combination, which follows the format
<namespace_id>.<account_id>. - The endpoint may vary. The most common endpoint used is the gRPC regional endpoint, which follows the format:
<region>.<cloud_provider>.api.temporal.io:7233. - For Namespaces with High Availability features with API key authentication enabled, use the gRPC Namespace endpoint:
<namespace>.<account>.tmprl.cloud:7233. This allows automated failover without needing to switch endpoints.
You can find the Namespace and Account ID, as well as the endpoint, on the Namespaces tab:

You can provide these connection options using environment variables, a configuration file, or directly in code.
- Environment Variables
- Configuration File
- Code
The following environment variables are required to connect to Temporal Cloud:
TEMPORAL_NAMESPACE: Your Namespace and Account ID combination in the format<namespace_id>.<account_id>.TEMPORAL_ADDRESS: The gRPC endpoint for your Temporal Cloud Namespace.TEMPORAL_API_KEY: Your API key value. Required if you are using API key authentication.TEMPORAL_TLS_CLIENT_CERT_DATAorTEMPORAL_TLS_CLIENT_CERT_PATH: Your mTLS client certificate data or file path. Required if you are using mTLS authentication.TEMPORAL_TLS_CLIENT_KEY_DATAorTEMPORAL_TLS_CLIENT_KEY_PATH: Your mTLS client private key data or file path. Required if you are using mTLS authentication.
Ensure these environment variables exist in your environment before running your Go application.
Import the envconfig package to set connection options for the Temporal Client using environment variables. The
MustLoadDefaultClientOptions function will automatically load all environment variables. For a list of all available
environment variables and their default values, refer to Environment Configuration.
For example, the following code snippet loads all environment variables and creates a Temporal Client with the options
specified in those variables. If you have defined a configuration file at either the default location
(~/.config/temporalio/temporal.toml) or a custom location specified by the TEMPORAL_CONFIG_FILE environment
variable, this will also load the default profile in the configuration file. However, any options set via environment
variables will take precedence.
package main
import (
"fmt"
"log"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)
func main() {
// Loads the "default" profile from the standard location and environment variables.
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close()
fmt.Printf("✅ Connected to Temporal namespace %q on %s\n", c.Options().Namespace, c.Options().HostPort)
}
You can use a TOML configuration file to set connection options for the Temporal Client. The configuration file lets you configure multiple profiles, each with its own set of connection options. You can then specify which profile to use when creating the Temporal Client.
You can use the environment variable TEMPORAL_CONFIG_FILE to specify the location of the TOML file or provide the path
to the file directly in code. If you don't provide the path to the configuration file, the SDK looks for it at the
default path ~/.config/temporalio/temporal.toml.
The connection options set in configuration files have lower precedence than environment variables. This means that if you set the same option in both the configuration file and as an environment variable, the environment variable value overrides the option set in the configuration file.
For example, the following TOML configuration file defines a cloud profile with the necessary connection options to
connect to Temporal Cloud via an API key:
# Cloud profile for Temporal Cloud
[profile.cloud]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
api_key = "your-api-key-here"
If you want to use mTLS authentication instead of an API key, replace the api_key field with your mTLS certificate and
private key:
# Cloud profile for Temporal Cloud
[profile.cloud]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
tls_client_cert_data = "your-tls-client-cert-data"
tls_client_key_path = "your-tls-client-key-path"
With the connections options defined in the configuration file, use the LoadClientOptions function in the envconfig
package to create a Temporal Client using the cloud profile as follows:
package main
import (
"fmt"
"log"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)
func main() {
// Replace with the actual path to your TOML file.
configFilePath := "/Users/yourname/.config/my-app/temporal.toml"
opts, err := envconfig.LoadClientOptions(envconfig.LoadClientOptionsRequest{
ConfigFilePath: configFilePath,
})
if err != nil {
log.Fatalf("Failed to load client config from custom file: %v", err)
}
c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect using custom config file: %v", err)
}
defer c.Close()
fmt.Printf("✅ Connected using custom config at: %s\n", configFilePath)
}
You can also provide connections options in your Go code directly. When instantiating a Temporal To update an API key, use the Go Create an initial connection: Update an API key: Create an initial connection: Update an API key:client in your
Temporal Go SDK code, provide the following clientOptions:v1.33.0+
clientOptions := client.Options{
HostPort: <endpoint>,
Namespace: <namespace_id>.<account_id>,
ConnectionOptions: client.ConnectionOptions{TLS: &tls.Config{}},
Credentials: client.NewAPIKeyStaticCredentials(apiKey),
}
c, err := client.Dial(clientOptions)context object:// Assuming client Credentials created with
var myKey string
creds := client.NewAPIKeyDynamicCredentials(
func(context.Context) (string, error) { return myKey, nil })
// Update by replacing
myKey = myKeyUpdatedv1.26.0 to v1.33.0 (exclusive)
clientOptions := client.Options{
HostPort: <endpoint>,
Namespace: <namespace_id>.<account_id>,
ConnectionOptions: client.ConnectionOptions{
TLS: &tls.Config{},
DialOptions: []grpc.DialOption{
grpc.WithUnaryInterceptor(
func(ctx context.Context, method string, req any, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
return invoker(
metadata.AppendToOutgoingContext(ctx, "temporal-namespace", <namespace_id>.<account_id>),
method,
req,
reply,
cc,
opts...,
)
},
),
},
},
Credentials: client.NewAPIKeyStaticCredentials(apiKey),
}
c, err := client.Dial(clientOptions)
if err != nil {
log.Fatalf("error creating temporal client: %v", err)
}// Assuming client Credentials created with
var myKey string
creds := client.NewAPIKeyDynamicCredentials(
func(context.Context) (string, error) { return myKey, nil })
// Just update by replacing
myKey = myKeyUpdatedpre v1.26.0
// Create headers provider
type APIKeyProvider struct {
APIKey string
Namespace string
}
func (a *APIKeyProvider) GetHeaders(context.Context) (map[string]string, error) {
return map[string]string{"Authorization": "Bearer " + a.APIKey, "temporal-namespace": a.Namespace}, nil
}
// Use headers provider
apiKeyProvider := &APIKeyProvider{APIKey: <APIKey>, Namespace: <namespace_id>.<account_id>}
c, err := client.Dial(client.Options{
HostPort: <endpoint>,
Namespace: <namespace_id>.<account_id>,
HeadersProvider: apiKeyProvider,
ConnectionOptions: client.ConnectionOptions{TLS: &tls.Config{
}},
})apiKeyProvider.APIKey = myKeyUpdated
Start Workflow Execution
How to start a Workflow Execution using the Go SDK
Workflow Execution semantics rely on several parameters—that is, to start a Workflow Execution you must supply a Task Queue that will be used for the Tasks (one that a Worker is polling), the Workflow Type, language-specific contextual data, and Workflow Function parameters.
In the examples below, all Workflow Executions are started using a Temporal Client. To spawn Workflow Executions from within another Workflow Execution, use either the Child Workflow or External Workflow APIs.
See the Customize Workflow Type section to see how to customize the name of the Workflow Type.
A request to spawn a Workflow Execution causes the Temporal Service to create the first Event (WorkflowExecutionStarted) in the Workflow Execution Event History. The Temporal Service then creates the first Workflow Task, resulting in the first WorkflowTaskScheduled Event.
To spawn a Workflow Execution, use the ExecuteWorkflow() method on the Go SDK
Client.
The ExecuteWorkflow() API call requires an instance of context.Context, an
instance of StartWorkflowOptions, a Workflow Type
name, and all variables to be passed to the Workflow Execution. The ExecuteWorkflow() call returns a Future, which can
be used to get the result of the Workflow Execution.
package main
import (
// ...
"go.temporal.io/sdk/client"
)
func main() {
temporalClient, err := client.Dial(client.Options{})
if err != nil {
// ...
}
defer temporalClient.Close()
// ...
workflowOptions := client.StartWorkflowOptions{
// ...
}
workflowRun, err := temporalClient.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition, param)
if err != nil {
// ...
}
// ...
}
func YourWorkflowDefinition(ctx workflow.Context, param YourWorkflowParam) (YourWorkflowResponse, error) {
// ...
}
If the invocation process has access to the function directly, then the Workflow Type name parameter can be passed as if the function name were a variable, without quotations.
workflowRun, err := temporalClient.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition, param)
If the invocation process does not have direct access to the statically defined Workflow Definition, for example, if the
Workflow Definition is in an un-importable package, or it is written in a completely different language, then the
Workflow Type can be provided as a string.
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, "YourWorkflowDefinition", param)
Set Workflow Task Queue
How to set a Workflow's Task Queue using the Go SDK
In most SDKs, the only Workflow Option that must be set is the name of the Task Queue.
For any code to execute, a Worker Process must be running that contains a Worker Entity that is polling the same Task Queue name.
Create an instance of
StartWorkflowOptions from the
go.temporal.io/sdk/client package, set the TaskQueue field, and pass the instance to the ExecuteWorkflow call.
- Type:
string - Default: None, this is a required field to be set by the developer
workflowOptions := client.StartWorkflowOptions{
// ...
TaskQueue: "your-task-queue",
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
You can configure Task Queues that are host-specific, Worker-specific or Workflow-specific to distribute your application load. For more information, refer to Task Queues Processing Tuning and Worker Versioning.
Set custom Workflow Id
How to set a custom Workflow Id using the Go SDK
Although it is not required, we recommend providing your own Workflow Idthat maps to a business process or business entity identifier, such as an order identifier or customer identifier.
Create an instance of
StartWorkflowOptions from the
go.temporal.io/sdk/client package, set the ID field, and pass the instance to the ExecuteWorkflow call.
- Type:
string - Default: System generated UUID
workflowOptions := client.StartWorkflowOptions{
// ...
ID: "Your-Custom-Workflow-Id",
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
Go StartWorkflowOptions reference
Create an instance of
StartWorkflowOptions from the
go.temporal.io/sdk/client package, and pass the instance to the ExecuteWorkflow call.
The following fields are available:
| Field | Required | Type |
|---|---|---|
ID | No | string |
TaskQueue | Yes | string |
WorkflowExecutionTimeout | No | time.Duration |
WorkflowRunTimeout | No | time.Duration |
WorkflowTaskTimeout | No | time.Duration |
WorkflowIDReusePolicy | No | WorkflowIdReusePolicy |
WorkflowExecutionErrorWhenAlreadyStarted | No | bool |
RetryPolicy | No | RetryPolicy |
CronSchedule | No | string |
Memo | No | map[string]interface{} |
SearchAttributes | No | map[string]interface{} |
ID
Although it is not required, we recommend providing your own Workflow Idthat maps to a business process or business entity identifier, such as an order identifier or customer identifier.
Create an instance of StartWorkflowOptions
from the go.temporal.io/sdk/client package, set the ID field, and pass the instance to the ExecuteWorkflow call.
- Type:
string - Default: System generated UUID
workflowOptions := client.StartWorkflowOptions{
// ...
ID: "Your-Custom-Workflow-Id",
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
TaskQueue
Create an instance of StartWorkflowOptions
from the go.temporal.io/sdk/client package, set the TaskQueue field, and pass the instance to the ExecuteWorkflow
call.
- Type:
string - Default: None; this is a required field to be set by the developer
workflowOptions := client.StartWorkflowOptions{
// ...
TaskQueue: "your-task-queue",
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
WorkflowExecutionTimeout
Create an instance of StartWorkflowOptions from the
go.temporal.io/sdk/client package, set the WorkflowExecutionTimeout field, and pass the instance to the
ExecuteWorkflow call.
- Type:
time.Duration - Default: Unlimited
workflowOptions := client.StartWorkflowOptions{
// ...
WorkflowExecutionTimeout: time.Hours * 24 * 365 * 10,
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
WorkflowRunTimeout
Create an instance of StartWorkflowOptions from the
go.temporal.io/sdk/client package, set the WorkflowRunTimeout field, and pass the instance to the ExecuteWorkflow
call.
- Type:
time.Duration - Default: Same as
WorkflowExecutionTimeout
workflowOptions := client.StartWorkflowOptions{
WorkflowRunTimeout: time.Hours * 24 * 365 * 10,
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
WorkflowTaskTimeout
Create an instance of StartWorkflowOptions from the
go.temporal.io/sdk/client package, set the WorkflowTaskTimeout field, and pass the instance to the ExecuteWorkflow
call.
- Type:
time.Duration - Default:
time.Seconds * 10
workflowOptions := client.StartWorkflowOptions{
WorkflowTaskTimeout: time.Second * 10,
//...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
WorkflowIDReusePolicy
- Type: WorkflowIdReusePolicy
- Default:
enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE
Set a value from the go.temporal.io/api/enums/v1 package.
workflowOptions := client.StartWorkflowOptions{
WorkflowIdReusePolicy: enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE,
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
WorkflowExecutionErrorWhenAlreadyStarted
- Type:
bool - Default:
false
workflowOptions := client.StartWorkflowOptions{
WorkflowExecutionErrorWhenAlreadyStarted: false,
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
RetryPolicy
Create an instance of a RetryPolicy from the
go.temporal.io/sdk/temporal package and provide it as the value to the RetryPolicy field of the instance of
StartWorkflowOptions.
- Type: RetryPolicy
- Default: None
retrypolicy := &temporal.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumInterval: time.Second * 100,
}
workflowOptions := client.StartWorkflowOptions{
RetryPolicy: retrypolicy,
// ...
}
workflowRun, err := temporalClient.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
CronSchedule
- Type:
string - Default: None
workflowOptions := client.StartWorkflowOptions{
CronSchedule: "15 8 * * *",
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
Memo
- Type:
map[string]interface{} - Default: Empty
workflowOptions := client.StartWorkflowOptions{
Memo: map[string]interface{}{
"description": "Test search attributes workflow",
},
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
SearchAttributes
How to set Workflow Execution Search Attributes in Go
- Type:
map[string]interface{} - Default: Empty.
These are the corresponding Search Attribute value types in Go:
- Keyword = string
- Int = int64
- Double = float64
- Bool = bool
- Datetime = time.Time
- Text = string
searchAttributes := map[string]interface{}{
"CustomIntField": 1,
"MiscData": "yellow",
}
workflowOptions := client.StartWorkflowOptions{
SearchAttributes: searchAttributes,
// ...
}
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition)
if err != nil {
// ...
}
Get Workflow results
How to get the results of a Workflow Execution using the Go SDK
If the call to start a Workflow Execution is successful, you will gain access to the Workflow Execution's Run Id.
The Workflow Id, Run Id, and Namespace may be used to uniquely identify a Workflow Execution in the system and get its result.
It's possible to both block progress on the result (synchronous execution) or get the result at some other point in time (asynchronous execution).
In the Temporal Platform, it's also acceptable to use Queries as the preferred method for accessing the state and results of Workflow Executions.
The ExecuteWorkflow call returns an instance of
WorkflowRun, which is the workflowRun variable in the
following line.
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, app.YourWorkflowDefinition, param)
if err != nil {
// ...
}
// ...
}
The instance of WorkflowRun has the following three methods:
GetWorkflowID(): Returns the Workflow Id of the invoked Workflow Execution.GetRunID(): Always returns the Run Id of the initial Run (See Continue As New) in the series of Runs that make up the full Workflow Execution.Get: Takes a pointer as a parameter and populates the associated variable with the Workflow Execution result.
To wait on the result of Workflow Execution in the same process that invoked it, call Get() on the instance of
WorkflowRun that is returned by the ExecuteWorkflow() call.
workflowRun, err := c.ExecuteWorkflow(context.Background(), workflowOptions, YourWorkflowDefinition, param)
if err != nil {
// ...
}
var result YourWorkflowResponse
err = workflowRun.Get(context.Background(), &result)
if err != nil {
// ...
}
// ...
}
However, the result of a Workflow Execution can be obtained from a completely different process. All that is needed is the Workflow Id. (A Run Id is optional if more than one closed Workflow Execution has the same Workflow Id.) The result of the Workflow Execution is available for as long as the Workflow Execution Event History remains in the system.
Call the GetWorkflow() method on an instance of the Go SDK Client and pass it the Workflow Id used to spawn the
Workflow Execution. Then call the Get() method on the instance of WorkflowRun that is returned, passing it a pointer
to populate the result.
// ...
workflowID := "Your-Custom-Workflow-Id"
workflowRun := c.GetWorkflow(context.Background, workflowID)
var result YourWorkflowResponse
err = workflowRun.Get(context.Background(), &result)
if err != nil {
// ...
}
// ...
Get last completion result
In the case of a Temporal Cron Job, you might need to get the result of the previous Workflow Run and use it in the current Workflow Run.
To do this, use the HasLastCompletionResult
and GetLastCompletionResult APIs, available
from the go.temporal.io/sdk/workflow package, directly in your
Workflow code.
type CronResult struct {
Count int
}
func YourCronWorkflowDefinition(ctx workflow.Context) (CronResult, error) {
count := 1
if workflow.HasLastCompletionResult(ctx) {
var lastResult CronResult
if err := workflow.GetLastCompletionResult(ctx, &lastResult); err == nil {
count = count + lastResult.Count
}
}
newResult := CronResult {
Count: count,
}
return newResult, nil
}
This will work even if one of the cron Workflow Runs fails. The next Workflow Run gets the result of the last successfully Completed Workflow Run.