Skip to content
/ go-fsm Public

A simple Non-Hierarchical Finite State Machine based on the event.

License

Notifications You must be signed in to change notification settings

xgfone/go-fsm

Repository files navigation

Go FSM GoDoc License Build Status

The package fsm provides a simple Non-Hierarchical Finite State Machine based on the event. Support Go 1.5+.

Install

$ go get -u github.com/xgfone/go-fsm

Example

mermaid-state-diagram

package main

import (
	"fmt"

	gofsm "github.com/xgfone/go-fsm"
)

func main() {
	const (
		StateFoo = gofsm.State("StateFoo")
		StateBar = gofsm.State("StateBar")
	)

	const (
		EventFoo = gofsm.Event("EventFoo")
		EventBar = gofsm.Event("EventBar")
	)

	fsm := gofsm.New()
	fsm.SetCurrent(StateFoo)

	/// Add the state transitions.
	var barCount int
	gofsm.Source(StateFoo).WithTarget(StateBar).WithEvent(EventBar).Add(fsm) // No Action
	gofsm.Target(StateFoo).WithSource(StateBar).WithEvent(EventFoo).
		WithAction(func(fsm *gofsm.FSM, data interface{}) (transition bool) { // Set Action
			// TODO: do business something

			// Here as the example, after trigger the event EventFoo two twice,
			// transition the state to the target.
			if barCount > 0 {
				barCount = 0
				transition = true
			} else {
				barCount++
			}
			return
		}).
		Add(fsm)

	/// Set the listener of the state change.
	fsm.OnEnter(func(s gofsm.State) { fmt.Printf("OnEnter: %s\n", s) })
	fsm.OnExit(func(s gofsm.State) { fmt.Printf("OnExit: %s\n", s) })

	fsm.OnEnterState(StateFoo, func(s gofsm.State) { fmt.Printf("OnEnterState: %s\n", s) })
	fsm.OnEnterState(StateBar, func(s gofsm.State) { fmt.Printf("OnEnterState: %s\n", s) })

	fsm.OnExitState(StateFoo, func(s gofsm.State) { fmt.Printf("OnExitState: %s\n", s) })
	fsm.OnExitState(StateBar, func(s gofsm.State) { fmt.Printf("OnExitState: %s\n", s) })

	fsm.OnTransition(func(last, current gofsm.State) {
		fmt.Printf("OnTransition: %s -> %s\n", last, current)
	})

	/// Print the states and events
	fmt.Printf("Events: %v\n", fsm.Events())
	fmt.Printf("States: %v\n", fsm.States())
	fmt.Printf("TerminationStates: %v\n", fsm.Terminations()) // No Termination States

	/// Send the events to the state machine
	fmt.Println("------ Transition ------")
	last := fsm.Current()
	err := fsm.SendEvent(EventBar, nil)
	fmt.Printf("Event: %s, State: %s -> %s, Result: %v\n\n", EventBar, last, fsm.Current(), err)

	fmt.Println("------ Transition ------")
	last = fsm.Current()
	err = fsm.SendEvent(EventFoo, nil)
	fmt.Printf("Event: %s, State: %s -> %s, Result: %v\n\n", EventFoo, last, fsm.Current(), err)

	fmt.Println("------ Transition ------")
	last = fsm.Current()
	err = fsm.SendEvent(EventFoo, nil)
	fmt.Printf("Event: %s, State: %s -> %s, Result: %v\n\n", EventFoo, last, fsm.Current(), err)

	fmt.Println("------ Transition ------")
	last = fsm.Current()
	err = fsm.SendEvent(EventFoo, nil)
	fmt.Printf("Event: %s, State: %s -> %s, Result: %v\n\n", EventFoo, last, fsm.Current(), err)

	fmt.Println("------ Transition ------")
	last = fsm.Current()
	err = fsm.SendEvent(EventBar, nil)
	fmt.Printf("Event: %s, State: %s -> %s, Result: %v\n\n", EventBar, last, fsm.Current(), err)

	// Print the Graphviz visualizer.
	fmt.Println("------ Graphviz ------")
	fmt.Println(fsm.VisualizeGraphviz())

	// Print the Mermaid FlowChart visualizer.
	fmt.Println("------ Mermaid FlowChart ------")
	fmt.Println(fsm.VisualizeMermaidFlowChart("#aaaaaa"))

	// Print the Mermaid StateDiagram visualizer.
	fmt.Println("------ Mermaid StateDiagram ------")
	fmt.Println(fsm.VisualizeMermaidStateDiagram())

	// Output:
	// Events: [EventBar EventFoo]
	// States: [StateFoo StateBar]
	// TerminationStates: []
	// ------ Transition ------
	// OnExitState: StateFoo
	// OnExit: StateFoo
	// OnEnterState: StateBar
	// OnEnter: StateBar
	// OnTransition: StateFoo -> StateBar
	// Event: EventBar, State: StateFoo -> StateBar, Result: <nil>
	//
	// ------ Transition ------
	// Event: EventFoo, State: StateBar -> StateBar, Result: source state 'StateBar' transition for the event 'EventFoo' is suspended
	//
	// ------ Transition ------
	// OnExitState: StateBar
	// OnExit: StateBar
	// OnEnterState: StateFoo
	// OnEnter: StateFoo
	// OnTransition: StateBar -> StateFoo
	// Event: EventFoo, State: StateBar -> StateFoo, Result: <nil>
	//
	// ------ Transition ------
	// Event: EventFoo, State: StateFoo -> StateFoo, Result: no transition for the event 'EventFoo'
	//
	// ------ Transition ------
	// OnExitState: StateFoo
	// OnExit: StateFoo
	// OnEnterState: StateBar
	// OnEnter: StateBar
	// OnTransition: StateFoo -> StateBar
	// Event: EventBar, State: StateFoo -> StateBar, Result: <nil>
	//
	// ------ Graphviz ------
	// digraph fsm {
	//     "StateBar" -> "StateFoo" [ label = "EventFoo" ];
	//     "StateFoo" -> "StateBar" [ label = "EventBar" ];
	//
	//     "StateBar";
	//     "StateFoo";
	// }
	//
	// ------ Mermaid FlowChart ------
	// graph LR
	//     id0[StateBar]
	//     id1[StateFoo]
	//
	//     id0 --> |EventFoo| id1
	//     id1 --> |EventBar| id0
	//
	//     style id0 fill:#aaaaaa
	//
	// ------ Mermaid StateDiagram ------
	// stateDiagram-v2
	//     [*] --> StateBar
	//     StateBar --> StateFoo: EventFoo
	//     StateFoo --> StateBar: EventBar
	//
}

About

A simple Non-Hierarchical Finite State Machine based on the event.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages