---
title: "Step decisions"
description: "Execute returns a StepDecision. It moves to next Steps, closes the"
canonical_url: "https://docs.superdurable.io/zh-Hans/reference/go/1.35.x/flows-and-steps/step-decisions/"
source: "docs/reference-go_versioned_docs/version-1.35.x/flows-and-steps/step-decisions.mdx"
locale: "zh-Hans"
---

# Step decisions

**Execute** returns a **StepDecision**. It moves to next Steps, closes the
Flow, or both stops this branch and cancels other Steps.

<a id="gotomulti"></a>

## Multiple next Steps

**GoTo** starts one next Step. **GoToMany** starts multiple next Steps. Each
Step movement has its own input and can also have its own
[Step options](https://docs.superdurable.io/zh-Hans/reference/go/1.35.x/flows-and-steps/step-options.md#stepoptions-override-per-stepexecution).

```go
func (route) Execute(_ dex.Context, input StepDecisionInput) (*dex.StepDecision, error) {
	switch input.Mode {
	case "graceful":
		return dex.GracefulComplete("done"), nil
	case "dead-end":
		return dex.GoToMany(
			dex.MovementOf(branchWorker{}, "left"),
			dex.MovementOf(branchWorker{}, "right"),
		), nil
	default:
		quote := Quote{Carrier: "winner", Price: 9}
		return dex.GoToMany(
			dex.MovementOf(carrierA{}, Quote{Carrier: "A", Price: 10}),
			dex.MovementOf(carrierB{}, Quote{Carrier: "B", Price: 12}),
			dex.MovementOf(winnerStep{}, quote),
		), nil
	}
}
```

Example: [examples/go/primitives/step-decision/workflow.go](https://github.com/superdurable/dex/tree/main/examples/go/primitives/step-decision/workflow.go)

<a id="close-decisions"></a>

## Close decisions

| Decision             | What it does                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **GracefulComplete** | Stops this branch and triggers the Flow to prepare for completion. When all branches and Steps are stopped, the Flow completes. |
| **DeadEnd**          | Stops this branch only.                                                                                                         |
| **ForceComplete**    | Completes the Flow immediately.                                                                                                 |
| **ForceFail**        | Fails the Flow immediately.                                                                                                     |

**GracefulComplete** and **ForceComplete** can return an output. **ForceFail**
returns a failure reason. The Flow result returns each output with the Step
type and Step execution ID. When multiple Steps complete gracefully, all their
outputs return together.

A Flow can have no active Steps and still keep running. **DeadEnd** stops this
branch without making a decision that triggers the Flow to complete.

```go
func (route) Execute(_ dex.Context, input StepDecisionInput) (*dex.StepDecision, error) {
	switch input.Mode {
	case "graceful":
		return dex.GracefulComplete("done"), nil
	case "dead-end":
		return dex.GoToMany(
			dex.MovementOf(branchWorker{}, "left"),
			dex.MovementOf(branchWorker{}, "right"),
		), nil
	default:
		quote := Quote{Carrier: "winner", Price: 9}
		return dex.GoToMany(
			dex.MovementOf(carrierA{}, Quote{Carrier: "A", Price: 10}),
			dex.MovementOf(carrierB{}, Quote{Carrier: "B", Price: 12}),
			dex.MovementOf(winnerStep{}, quote),
		), nil
	}
}

func (branchWorker) Execute(_ dex.Context, _ string) (*dex.StepDecision, error) {
	return dex.DeadEnd(), nil
}
```

Example: [examples/go/primitives/step-decision/workflow.go](https://github.com/superdurable/dex/tree/main/examples/go/primitives/step-decision/workflow.go)

```go
func (*FlowGracefulTimeout) HandleTimeout(
	_ dex.Context,
) (*dex.StepDecision, error) {
	return dex.ForceFail("Workflow did not finish the task in time"), nil
}

func (longWait) Execute(
	_ dex.Context,
	_ bool,
) (*dex.StepDecision, error) {
	return dex.ForceComplete("Workflow completed successfully"), nil
}
```

Example: [examples/go/patterns/timeout/workflow.go](https://github.com/superdurable/dex/tree/main/examples/go/patterns/timeout/workflow.go)

<a id="cancellation-on-stepdecision"></a>

## Cancel other Steps

A **StepDecision** can cancel other active Steps.

- **CancelSteps** selects active Steps by Step type.
- **CancelSiblingSteps** selects active Steps that were triggered by the same
  parent Step execution.

An RPC can also cancel Steps by type. See
[Cancel running Steps](https://docs.superdurable.io/zh-Hans/reference/server/runtime-data.md#cancel-running-steps). For how a
running attempt observes cancellation, see [Cancellation](https://docs.superdurable.io/zh-Hans/reference/go/1.35.x/flows-and-steps/step-options.md#cancellation).

```go
func (winnerStep) Execute(_ dex.Context, quote Quote) (*dex.StepDecision, error) {
	return dex.GoTo(recordQuote{}, quote).
		CancelSteps(carrierA{}, carrierB{}), nil
}
```

Example: [examples/go/primitives/step-decision/workflow.go](https://github.com/superdurable/dex/tree/main/examples/go/primitives/step-decision/workflow.go)

<a id="forcecompleteifchannelsempty"></a>

## ForceCompleteIfChannelsEmpty

**ForceCompleteIfChannelsEmpty** atomically checks whether all named Channels
are empty. A Channel with queued messages is non-empty. After a message is
consumed and committed to a Step, that Channel remains non-empty until the Step
finishes processing **Execute**. If every named Channel is empty, it completes
the Flow. Otherwise, it goes to other Steps.

Use it to drain Channels and complete the Flow, so the Flow can stay short. See
[Drain External Channel](https://docs.superdurable.io/zh-Hans/design-patterns/draining-channel-for-external-publishing.md)
for the full example.

```go
return dex.ForceCompleteIfChannelsEmpty(
	nil,
	[]dex.ChannelDef{QueueChannel},
	dex.MovementOf(processMessage{}, ""),
), nil
```

Example: [examples/go/patterns/drain-channels/external-publishing/workflow.go](https://github.com/superdurable/dex/tree/main/examples/go/patterns/drain-channels/external-publishing/workflow.go)
