Movatterモバイル変換


[0]ホーム

URL:


fsm

packagemodule
v1.0.3Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2025 License:Apache-2.0Imports:7Imported by:668

Details

Repository

github.com/looplab/fsm

Links

README

PkgGoDevBulid StatusCoverage StatusGo Report Card

FSM for Go

FSM is a finite state machine for Go.

It is heavily based on two FSM implementations:

For API docs and examples seehttp://godoc.org/github.com/looplab/fsm

Basic Example

From examples/simple.go:

package mainimport (    "context"    "fmt"    "github.com/looplab/fsm")func main() {    fsm := fsm.NewFSM(        "closed",        fsm.Events{            {Name: "open", Src: []string{"closed"}, Dst: "open"},            {Name: "close", Src: []string{"open"}, Dst: "closed"},        },        fsm.Callbacks{},    )    fmt.Println(fsm.Current())    err := fsm.Event(context.Background(), "open")    if err != nil {        fmt.Println(err)    }    fmt.Println(fsm.Current())    err = fsm.Event(context.Background(), "close")    if err != nil {        fmt.Println(err)    }    fmt.Println(fsm.Current())}

Usage as a struct field

From examples/struct.go:

package mainimport (    "context"    "fmt"    "github.com/looplab/fsm")type Door struct {    To  string    FSM *fsm.FSM}func NewDoor(to string) *Door {    d := &Door{        To: to,    }    d.FSM = fsm.NewFSM(        "closed",        fsm.Events{            {Name: "open", Src: []string{"closed"}, Dst: "open"},            {Name: "close", Src: []string{"open"}, Dst: "closed"},        },        fsm.Callbacks{            "enter_state": func(_ context.Context, e *fsm.Event) { d.enterState(e) },        },    )    return d}func (d *Door) enterState(e *fsm.Event) {    fmt.Printf("The door to %s is %s\n", d.To, e.Dst)}func main() {    door := NewDoor("heaven")    err := door.FSM.Event(context.Background(), "open")    if err != nil {        fmt.Println(err)    }    err = door.FSM.Event(context.Background(), "close")    if err != nil {        fmt.Println(err)    }}

License

FSM is licensed under Apache License 2.0

http://www.apache.org/licenses/LICENSE-2.0

Documentation

Overview

Package fsm implements a finite state machine.

It is heavily based on two FSM implementations:

Javascript Finite State Machinehttps://github.com/jakesgordon/javascript-state-machine

Fysom for Pythonhttps://github.com/oxplot/fysom (forked athttps://github.com/mriehl/fysom)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

funcVisualize

func Visualize(fsm *FSM)string

Visualize outputs a visualization of a FSM in Graphviz format.

funcVisualizeForMermaidWithGraphTypeadded inv0.2.0

func VisualizeForMermaidWithGraphType(fsm *FSM, graphTypeMermaidDiagramType) (string,error)

VisualizeForMermaidWithGraphType outputs a visualization of a FSM in Mermaid format as specified by the graphType.

funcVisualizeWithTypeadded inv0.2.0

func VisualizeWithType(fsm *FSM, visualizeTypeVisualizeType) (string,error)

VisualizeWithType outputs a visualization of a FSM in the desired format.If the type is not given it defaults to GRAPHVIZ

Types

typeAsyncError

type AsyncError struct {ErrerrorCtxcontext.ContextCancelTransition func()}

AsyncError is returned by FSM.Event() when a callback have initiated anasynchronous state transition.

func (AsyncError)Error

func (eAsyncError) Error()string

func (AsyncError)Unwrapadded inv1.0.3

func (eAsyncError) Unwrap()error

typeCallback

type Callback func(context.Context, *Event)

Callback is a function type that callbacks should use. Event is the currentevent info as the callback happens.

typeCallbacks

type Callbacks map[string]Callback

Callbacks is a shorthand for defining the callbacks in NewFSM.

typeCanceledError

type CanceledError struct {Errerror}

CanceledError is returned by FSM.Event() when a callback have canceled atransition.

func (CanceledError)Error

func (eCanceledError) Error()string

func (CanceledError)Unwrapadded inv1.0.3

func (eCanceledError) Unwrap()error

typeEvent

type Event struct {// FSM is an reference to the current FSM.FSM *FSM// Event is the event name.Eventstring// Src is the state before the transition.Srcstring// Dst is the state after the transition.Dststring// Err is an optional error that can be returned from a callback.Errerror// Args is an optional list of arguments passed to the callback.Args []interface{}// contains filtered or unexported fields}

Event is the info that get passed as a reference in the callbacks.

func (*Event)Async

func (e *Event) Async()

Async can be called in leave_<STATE> to do an asynchronous state transition.

The current state transition will be on hold in the old state until a finalcall to Transition is made. This will complete the transition and possiblycall the other callbacks.

func (*Event)Cancel

func (e *Event) Cancel(err ...error)

Cancel can be called in before_<EVENT> or leave_<STATE> to cancel thecurrent transition before it happens. It takes an optional error, which willoverwrite e.Err if set before.

typeEventDesc

type EventDesc struct {// Name is the event name used when calling for a transition.Namestring// Src is a slice of source states that the FSM must be in to perform a// state transition.Src []string// Dst is the destination state that the FSM will be in if the transition// succeeds.Dststring}

EventDesc represents an event when initializing the FSM.

The event can have one or more source states that is valid for performingthe transition. If the FSM is in one of the source states it will end up inthe specified destination state, calling all defined callbacks as it goes.

typeEvents

type Events []EventDesc

Events is a shorthand for defining the transition map in NewFSM.

typeFSM

type FSM struct {// contains filtered or unexported fields}

FSM is the state machine that holds the current state.

It has to be created with NewFSM to function properly.

funcNewFSM

func NewFSM(initialstring, events []EventDesc, callbacks map[string]Callback) *FSM

NewFSM constructs a FSM from events and callbacks.

The events and transitions are specified as a slice of Event structsspecified as Events. Each Event is mapped to one or more internaltransitions from Event.Src to Event.Dst.

Callbacks are added as a map specified as Callbacks where the key is parsedas the callback event as follows, and called in the same order:

1. before_<EVENT> - called before event named <EVENT>

2. before_event - called before all events

3. leave_<OLD_STATE> - called before leaving <OLD_STATE>

4. leave_state - called before leaving all states

5. enter_<NEW_STATE> - called after entering <NEW_STATE>

6. enter_state - called after entering all states

7. after_<EVENT> - called after event named <EVENT>

8. after_event - called after all events

There are also two short form versions for the most commonly used callbacks.They are simply the name of the event or state:

1. <NEW_STATE> - called after entering <NEW_STATE>

2. <EVENT> - called after event named <EVENT>

If both a shorthand version and a full version is specified it is undefinedwhich version of the callback will end up in the internal map. This is dueto the pseudo random nature of Go maps. No checking for multiple keys iscurrently performed.

Example
fsm := NewFSM("green",Events{{Name: "warn", Src: []string{"green"}, Dst: "yellow"},{Name: "panic", Src: []string{"yellow"}, Dst: "red"},{Name: "panic", Src: []string{"green"}, Dst: "red"},{Name: "calm", Src: []string{"red"}, Dst: "yellow"},{Name: "clear", Src: []string{"yellow"}, Dst: "green"},},Callbacks{"before_warn": func(_ context.Context, e *Event) {fmt.Println("before_warn")},"before_event": func(_ context.Context, e *Event) {fmt.Println("before_event")},"leave_green": func(_ context.Context, e *Event) {fmt.Println("leave_green")},"leave_state": func(_ context.Context, e *Event) {fmt.Println("leave_state")},"enter_yellow": func(_ context.Context, e *Event) {fmt.Println("enter_yellow")},"enter_state": func(_ context.Context, e *Event) {fmt.Println("enter_state")},"after_warn": func(_ context.Context, e *Event) {fmt.Println("after_warn")},"after_event": func(_ context.Context, e *Event) {fmt.Println("after_event")},},)fmt.Println(fsm.Current())err := fsm.Event(context.Background(), "warn")if err != nil {fmt.Println(err)}fmt.Println(fsm.Current())
Output:greenbefore_warnbefore_eventleave_greenleave_stateenter_yellowenter_stateafter_warnafter_eventyellow

func (*FSM)AvailableTransitions

func (f *FSM) AvailableTransitions() []string

AvailableTransitions returns a list of transitions available in thecurrent state.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},{Name: "kick", Src: []string{"closed"}, Dst: "broken"},},Callbacks{},)// sort the results ordering is consistent for the output checkertransitions := fsm.AvailableTransitions()sort.Strings(transitions)fmt.Println(transitions)
Output:[kick open]

func (*FSM)Can

func (f *FSM) Can(eventstring)bool

Can returns true if event can occur in the current state.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{},)fmt.Println(fsm.Can("open"))fmt.Println(fsm.Can("close"))
Output:truefalse

func (*FSM)Cannot

func (f *FSM) Cannot(eventstring)bool

Cannot returns true if event can not occur in the current state.It is a convenience method to help code read nicely.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{},)fmt.Println(fsm.Cannot("open"))fmt.Println(fsm.Cannot("close"))
Output:falsetrue

func (*FSM)Current

func (f *FSM) Current()string

Current returns the current state of the FSM.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{},)fmt.Println(fsm.Current())
Output:closed

func (*FSM)DeleteMetadataadded inv1.0.0

func (f *FSM) DeleteMetadata(keystring)

DeleteMetadata deletes the dataValue in metadata by key

func (*FSM)Event

func (f *FSM) Event(ctxcontext.Context, eventstring, args ...interface{})error

Event initiates a state transition with the named event.

The call takes a variable number of arguments that will be passed to thecallback, if defined.

It will return nil if the state change is ok or one of these errors:

- event X inappropriate because previous transition did not complete

- event X inappropriate in current state Y

- event X does not exist

- internal error on state transition

The last error should never occur in this situation and is a sign of aninternal bug.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{},)fmt.Println(fsm.Current())err := fsm.Event(context.Background(), "open")if err != nil {fmt.Println(err)}fmt.Println(fsm.Current())err = fsm.Event(context.Background(), "close")if err != nil {fmt.Println(err)}fmt.Println(fsm.Current())
Output:closedopenclosed

func (*FSM)Is

func (f *FSM) Is(statestring)bool

Is returns true if state is the current state.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{},)fmt.Println(fsm.Is("closed"))fmt.Println(fsm.Is("open"))
Output:truefalse

func (*FSM)Metadataadded inv0.3.0

func (f *FSM) Metadata(keystring) (interface{},bool)

Metadata returns the value stored in metadata

func (*FSM)SetMetadataadded inv0.3.0

func (f *FSM) SetMetadata(keystring, dataValue interface{})

SetMetadata stores the dataValue in metadata indexing it with key

func (*FSM)SetState

func (f *FSM) SetState(statestring)

SetState allows the user to move to the given state from current state.The call does not trigger any callbacks, if defined.

func (*FSM)Transition

func (f *FSM) Transition()error

Transition wraps transitioner.transition.

Example
fsm := NewFSM("closed",Events{{Name: "open", Src: []string{"closed"}, Dst: "open"},{Name: "close", Src: []string{"open"}, Dst: "closed"},},Callbacks{"leave_closed": func(_ context.Context, e *Event) {e.Async()},},)err := fsm.Event(context.Background(), "open")if e, ok := err.(AsyncError); !ok && e.Err != nil {fmt.Println(err)}fmt.Println(fsm.Current())err = fsm.Transition()if err != nil {fmt.Println(err)}fmt.Println(fsm.Current())
Output:closedopen

typeInTransitionError

type InTransitionError struct {Eventstring}

InTransitionError is returned by FSM.Event() when an asynchronous transitionis already in progress.

func (InTransitionError)Error

func (eInTransitionError) Error()string

typeInternalError

type InternalError struct{}

InternalError is returned by FSM.Event() and should never occur. It is aprobably because of a bug.

func (InternalError)Error

func (eInternalError) Error()string

typeInvalidEventError

type InvalidEventError struct {EventstringStatestring}

InvalidEventError is returned by FSM.Event() when the event cannot be calledin the current state.

func (InvalidEventError)Error

func (eInvalidEventError) Error()string

typeMermaidDiagramTypeadded inv0.2.0

type MermaidDiagramTypestring

MermaidDiagramType the type of the mermaid diagram type

const (// FlowChart the diagram type for output in flowchart style (https://mermaid-js.github.io/mermaid/#/flowchart) (including current state)FlowChartMermaidDiagramType = "flowChart"// StateDiagram the diagram type for output in stateDiagram style (https://mermaid-js.github.io/mermaid/#/stateDiagram)StateDiagramMermaidDiagramType = "stateDiagram")

typeNoTransitionError

type NoTransitionError struct {Errerror}

NoTransitionError is returned by FSM.Event() when no transition have happened,for example if the source and destination states are the same.

func (NoTransitionError)Error

func (eNoTransitionError) Error()string

func (NoTransitionError)Unwrapadded inv1.0.3

func (eNoTransitionError) Unwrap()error

typeNotInTransitionError

type NotInTransitionError struct{}

NotInTransitionError is returned by FSM.Transition() when an asynchronoustransition is not in progress.

func (NotInTransitionError)Error

typeUnknownEventError

type UnknownEventError struct {Eventstring}

UnknownEventError is returned by FSM.Event() when the event is not defined.

func (UnknownEventError)Error

func (eUnknownEventError) Error()string

typeVisualizeTypeadded inv0.2.0

type VisualizeTypestring

VisualizeType the type of the visualization

const (// GRAPHVIZ the type for graphviz output (http://www.webgraphviz.com/)GRAPHVIZVisualizeType = "graphviz"// MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram formMERMAIDVisualizeType = "mermaid"// MermaidStateDiagram the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram formMermaidStateDiagramVisualizeType = "mermaid-state-diagram"// MermaidFlowChart the type for mermaid output (https://mermaid-js.github.io/mermaid/#/flowchart) in the flow chart formMermaidFlowChartVisualizeType = "mermaid-flow-chart")

Source Files

View all Source files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp