Develop a Workflow in Go
In the Temporal Go SDK programming model, a Workflow Definition is an exportable function.
func YourWorkflowDefinition(ctx workflow.Context) error {
// ...
return nil
}
In Go, by default, the Workflow Type name is the same as the function name.
Parameters
The first parameter of a Go-based Workflow Definition must be of the workflow.Context
type, as it is used by the Temporal Go SDK to pass around Workflow Execution context, and virtually all the Go SDK APIs that are callable from the Workflow require it.
It is acquired from the go.temporal.io/sdk/workflow
package.
import (
"go.temporal.io/sdk/workflow"
)
func YourWorkflowDefinition(ctx workflow.Context, param string) error {
// ...
}
The workflow.Context
entity operates similarly to the standard context.Context
entity provided by Go.
The only difference between workflow.Context
and context.Context
is that the Done()
function, provided by workflow.Context
, returns workflow.Channel
instead of the standard Go chan
.
The second parameter, string
, is a custom parameter that is passed to the Workflow when it is invoked.
A Workflow Definition may support multiple custom parameters, or none.
These parameters can be regular type variables or safe pointers.
However, the best practice is to pass a single parameter that is of a struct
type, so there can be some backward compatibility if new parameters are added.
type YourWorkflowParam struct {
WorkflowParamFieldOne string
WorkflowParamFieldTwo int
}
func YourWorkflowDefinition(ctx workflow.Context, param YourWorkflowParam) error {
// ...
}
All Workflow Definition parameters must be serializable, regardless of whether pointers or regular type values are used. Parameters can’t be channels, functions, variadic, or unsafe pointers.
Return values
A Go-based Workflow Definition can return either just an error
or a customValue, error
combination.
Again, the best practice here is to use a struct
type to hold all custom values.
type YourWorkflowResponse struct{
WorkflowResultFieldOne string
WorkflowResultFieldTwo int
}
func YourWorkflowDefinition(ctx workflow.Context, param YourWorkflowParam) (YourWorkflowResponse, error) {
// ...
if err != nil {
return "", err
}
responseVar := YourWorkflowResponse {
FieldOne: "super",
FieldTwo: 1,
}
return responseVar, nil
}
A Workflow Definition written in Go can return both a custom value and an error.
However, it's not possible to receive both a custom value and an error in the calling process, as is normal in Go.
The caller will receive either one or the other.
Returning a non-nil error
from a Workflow indicates that an error was encountered during its execution and the Workflow Execution should be terminated, and any custom return values will be ignored by the system.
Logic requirements
In Go, Workflow Definition code cannot directly do the following:
- Iterate over maps using
range
, because withrange
the order of the map's iteration is randomized. Instead you can collect the keys of the map, sort them, and then iterate over the sorted keys to access the map. This technique provides deterministic results. You can also use a Side Effect or an Activity to process the map instead. - Call an external API, conduct a file I/O operation, talk to another service, etc. (Use an Activity for these.)
The Temporal Go SDK has APIs to handle equivalent Go constructs:
workflow.Now()
This is a replacement fortime.Now()
.workflow.Sleep()
This is a replacement fortime.Sleep()
.workflow.GetLogger()
This ensures that the provided logger does not duplicate logs during a replay.workflow.Go()
This is a replacement for thego
statement.workflow.Channel
This is a replacement for the nativechan
type. Temporal provides support for both buffered and unbuffered channels.workflow.Selector
This is a replacement for theselect
statement. Learn more on the Go SDK Selectors pageworkflow.Context
This is a replacement forcontext.Context
. Learn more on the Go SDK Context Propagation page.