This is a creation in Article, where the information may have evolved or changed.
The GOFSM is a simple, compact, and characteristic finite state machine (FSM).
GitHub already has a few state machine implementations, such as the following, and why invent wheels again?
The reason is that the state machine has a feature, is a state machine to maintain the state of an object, so that a state machine and a specific image instance is associated with, in some cases, this is not a problem, and is a good design, and more in line with the definition of state machine. However, in some cases, when we need to maintain hundreds of objects, we need to create hundreds of state machine objects, which is actually a great waste, because in most cases, the object itself will maintain/maintain its own current state, we just need to pass the object's current state to a common state machine can be, That is, GOFSM itself is "stateless", itself it package to maintain the state of one or more objects, all the input required by the caller input, it is only responsible for the state of the logic of the transformation, so its implementation is very concise and practical, which is to create a GOFSM purpose.
The second reason it provides a unified interface for Moore and mealy two state machines and provides a UML state machine-style action handler that handles state changes in a way that programmers are more familiar with.
The third reason, when we talk about the state machine, we always draw a state transition diagram, you can discuss, design, implement and verify the migration of State based on this diagram. But for the code, the implementation is really consistent with your design, how can you guarantee? GOFSM provides a simple way to output images or PDF files, and you can use the output state machine diagram to compare your design to see if the implementation and design are consistent.
Finite state machine
Finite state machines (finite-state machine) are often used to design mathematical models of computer programs and sequential logic circuits. It is seen as an abstract machine that can have a finite state. At any moment the machine has only one state, which is called the current state. When an external event or condition is triggered, it can transition from one state to another, which is the conversion (transition). An FSM is defined by all States, the initial state, and the triggering conditions of each transition. Sometimes, when this transition happens, we can do something that we call an action.
In reality, we actually encounter a lot of this state machine situation, but we do not abstract them out, such as the intersection of the traffic lights, always in the red, yellow, green state between the change, such as the state of the elevator, including open, close, upper, and inferior several states.
Finite state machine can be used to establish a large number of problems clearly for the model, a lot of applications in electronic design, communication protocols, language analysis and other engineering applications, such as the TCP/IP protocol stack.
Take a revolving door for example, this specialized in some exhibition, museum, Park Gate is very common, customer can coin or swipe a ticket to enter, we hereafter use coin (Coin) collectively refer to this trigger event. If you do not vote, the gate is locked, you can not push its arm, and cast a coin only into a person, the past after the gate is locked, very smart:).
If we abstract out its state diagram, it can be represented by:
It has two states: Locked , Unlocked . There are two inputs (input) that affect its state, coin (coin) and push-arm (push).
- In the locked state, push has no effect. No matter how many times you push the gate or lock
- In the locked state, the coin will let the gate unlock, the gate can let a person through
- In the unlocked state, the coin does not work, the gate is still open
- In the unlocked state, if someone push through, the gate will be changed from unlocked state to locked state.
This is a simple gate state transition, but it is a typical example of a good understanding of the state.
It is represented by a table:
| Current state
Input |
Next | State
Output |
| Locked |
Coin |
Unlocked |
Unlock turnstile So customer can push through |
| Push |
Locked |
None |
| Unlocked |
Coin |
Unlocked |
None |
| Push |
Locked |
When the customer has pushed through, lock turnstile |
UML also has the change of state diagram, it expands the concept of FSM, provides the hierarchical nesting state (hierarchically nested states) and orthogonal region (orthogonal regions), of course, this does not have much relation with this article, Interested readers can find UML information to see. But it provides a good idea, the action. Just like the mealy state machine requires, the action relies on the state of the system and the triggering event, while its entry action and exit action, like the Moore state machine, do not depend on the input, only the state. So there are three types of UML actions, one is when events are processed, state opportunities perform specific actions, such as changing variables, executing I/O, invoking methods, triggering another event, and so on. Instead of leaving a state, you can execute the exit action and enter a state, then execute the entry action. Remember that when an event is received, the state of the object does not change, such as an example of the top gate, the number of times the push state is not changed in the locked state, in which case the exit and entry action are not executed.
GOFSM provides this extended model, of course, if you do not want to use this extension, you can also not implement entry and exit.
Two state machines can be mentioned, the two state machines being differentiated as follows:
- Moore Machine
The Moore state machine uses only the entry action, and the output depends only on the state and not on the input.
- Mealy Machine
The mealy state machine uses the input action only, and the output relies on inputs and states state. Using this state machine can usually reduce the number of States.
GOFSM provides a common interface that you can determine which state machine to use as needed. From the perspective of software development, sometimes you don't have to focus on the distinction of state machines, but rather on the clear abstraction, the state of the object you are focusing on, the trigger conditions, and the actions to be performed.
Gofsm
GOFSM the implementation of ELIMISTEVE/FSM, a single state machine is used to process multiple objects, and the function of the output state graph is provided.
In addition to defining the state of an object, it defines the trigger event and the action to be processed, which are represented by a string, and are easily mapped to your object or method when used.
Using GOFSM is also very simple, of course the first step will be to local:
1 |
Go get-u GITHUB.COM/SMALLNEST/GOFSM |
Let's take the above gate as an example to see how GOFSM is used.
Note that the following single state machine can handle the state change of multiple gates in parallel, although only one gate object is generated in the example.
First, define a gate object that contains a state that represents its current status:
12345678 |
type struct {ID UInt64 UInt64 //Event Statistics Coincount UInt64//coin Event Statistics passcount uint64//customer via event stats State string//Current state states []string//History through State } |
The initialization of the state machine is straightforward:
123456789101112 |
funcINITFSM () *statemachine {delegate: = &defaultdelegate{p: &turnstileeventprocessor{}}transitions: = [] Transition{transition{from:"Locked", Event:"Coin", to:"Unlocked", Action:"Check"},transition{from:"Locked", Event:"Push", to:"Locked", Action:"Invalid-push"},transition{from:"Unlocked", Event:"Push", to:"Locked", Action:"Pass"},transition{from:"Unlocked", Event:"Coin", to:"Unlocked", Action:"Repeat-check"},}returnNewstatemachine (delegate, transitions ...)} |
You define the transformation correspondence transitions , one that Transition represents a transition, from one state to another, the event name to trigger, and the action to execute.
Because the action is a string, you need to implement the delegate corresponding action and the corresponding method to be processed.
Note that the from and to States can be the same, in which case the state does not change, just need to handle the action.
If the action is empty, that is, there is no need to handle the event, only the state changes.
The type of action to handle is as follows:
12345678910111213 |
type struct {}funcstring, args []interface{}) {...} func string string string, args []interface{}) {...} func string, args []interface{}) { ...} |
Then we can trigger some events to see if the gate's state machine is working properly:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
TS: = &turnstile{id:1, State:"Locked", states: []string{"Locked"},}FSM: = INITFSM ()//Push the door//No card/coin is not allowedERR: = FSM. Trigger (TS. State,"Push", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}//Push the door//No card/coin is not allowedErr = FSM. Trigger (TS. State,"Push", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}//swipe or coin//Not easy Ah, finally unlockedErr = FSM. Trigger (TS. State,"Coin", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}//swipe or coin//Then unlockErr = FSM. Trigger (TS. State,"Coin", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}//Push the door//At this time to enter, enter the rear gate is lockedErr = FSM. Trigger (TS. State,"Push", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}//Push the door//cannot enter, the gate is lockedErr = FSM. Trigger (TS. State,"Push", TS)ifErr! =Nil{T.errorf ("Trigger err:%v", err)}laststate: = Turnstile{id:1, EventCount:6, Coincount:2, Passcount:1, State:"Locked", states: []string{"Locked","Unlocked","Locked"},}if!compareturnstile (&laststate, ts) {T.errorf ("expected last state:%+v, but got%+v", LastState, TS)}Else{T.LOGF ("final state:%+v", TS)} |
If you want to export the state graph, you can call the following method, which is actually called Graphviz generated, so please make sure that the software is installed on your machine, you can perform a dot -h check:
1 |
Fsm. Export ("State.png") |
The resulting picture is the picture of the state machine of the gate of the text head.
If you want to customize the parameters of the Graphviz, you can call another method:
1 |
func string string string string string) Error |
Other go language-implemented FSM
If you find that GOFSM features need to be improved, or have some ideas, or found bugs, please do not hesitate to submit your comments and suggestions in issue, I will timely feedback.
If you think this project is useful, or may be used in the future, please star this project SMALLNEST/GOFSM.
If you want to compare other implementations of the Go language FSM, you can refer to the following list:
- Elimisteve/fsm
- Looplab/fsm
- Vaughan0/go-fsm
- Watchbeam/fsm
- Discoviking/fsm
- Autocube/hsm
- Theckman/go-fsm
- Zumata/fsm
- Syed/go-fsm
- Go-rut/fsm
- Yandd/fsm
- Go-trellis/fsm
- ......
Resources
- Https://en.wikipedia.org/wiki/Finite-state_machine