go-maquina icon indicating copy to clipboard operation
go-maquina copied to clipboard

Small finite-state machine library for Go

go.dev reference Go Report Card License: MIT

go-maquina

Create finite-state machines in Go. Inspired by stateless.

Maquina is the spanish word for machine. It is pronounced maa-kee-nuh, much like machina from the Latin calque deus-ex-machina.

Code organization

  • maquina.go contains internal logic for the state machine such as the fire() functions triggered by a state transition.

  • state.go contains most of the user visible exported methods on State type.

  • statemachine.go contains code relevant to the State manager StateMachine.

Toll booth example

	const (
		passageCost                      = 10.00
		defaultPay                       = 0.0
		payUp            maquina.Trigger = "customer pays"
		customerAdvances maquina.Trigger = "customer advances"
	)

	tollClosed := maquina.NewState("toll barrier closed", defaultPay)
	tollOpen := maquina.NewState("toll barrier open", defaultPay)

	tollClosed.Permit(payUp, tollOpen, func(_ context.Context, pay float64) error {
		if pay < passageCost {
			// Barrier remains closed unless customer pays up
			return fmt.Errorf("customer underpaid with $%.2f", pay)
		}
		return nil
	})
	tollOpen.Permit(customerAdvances, tollClosed)

	SM := maquina.NewStateMachine(tollClosed)
	for i := 0; i < 5; i++ {
		pay := 2 * passageCost * rand.Float64()
		// FireBg activates transition with context.Background()
		err := SM.FireBg(payUp, pay)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Printf("customer paid $%.2f, let them pass!\n", pay)
			SM.FireBg(customerAdvances, 0)
		}
	}

The code above outputs:

customer paid $12.09, let them pass!
customer paid $18.81, let them pass!
customer paid $13.29, let them pass!
guard clause failed: customer underpaid with $8.75
guard clause failed: customer underpaid with $8.49