package main import ( "context" "fmt" "log" "github.com/looplab/fsm" ) func main() { var afterFinishCalled bool cbs := make(fsm.Callbacks) for _, name := range []string{ // Events: before, after "run", "finish", "reset", // States: enter, leave "start", "end", "finished", } { for _, op := range []string{"before_", "after_", "leave_", "enter_"} { cbs[op+name] = func(ctx context.Context, event *fsm.Event) { log.Printf("%s", op+name) } } } cbs["enter_end"] = func(ctx context.Context, e *fsm.Event) { log.Println("enter end") if err := e.FSM.Event(ctx, "finish"); err != nil { fmt.Println(err) } } cbs["after_finish"] = func(ctx context.Context, e *fsm.Event) { log.Println("after finish") afterFinishCalled = true if e.Src != "end" { panic(fmt.Sprintf("source should have been 'end' but was '%s'", e.Src)) } if err := e.FSM.Event(ctx, "reset"); err != nil { fmt.Println(err) } } machine := fsm.NewFSM( "start", fsm.Events{ {Name: "run", Src: []string{"start"}, Dst: "end"}, {Name: "finish", Src: []string{"end"}, Dst: "finished"}, {Name: "reset", Src: []string{"end", "finished"}, Dst: "start"}, }, cbs, ) if err := machine.Event(context.Background(), "run"); err != nil { panic(fmt.Sprintf("Error encountered when triggering the run event: %v", err)) } if !afterFinishCalled { //panic(fmt.Sprintf("After finish callback should have run, current state: '%s'", machine.Current())) } currentState := machine.Current() if currentState != "start" { panic(fmt.Sprintf("expected state to be 'start', was '%s'", currentState)) } fmt.Println("Successfully ran state machine.") //fmt.Println(fsm.VisualizeForMermaidWithGraphType(machine, fsm.StateDiagram)) fmt.Println(fsm.VisualizeWithType(machine, fsm.GRAPHVIZ)) }