Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@souhei-etou

golangで始めるstate machine

仕事でチャットボットを作る可能性があり、セリフ管理にstate machineが使えるかもということで、golang で state machineを触ってみました。

state machine とは?

image.png

図のように、ある状態からある状態へ遷移するなどの構造を表したものです。
なので、現在のstate -> 遷移可能なstate -> 次のstateの情報をそれぞれのnodeが持つことになります。

尚正式名称は finite state machine と呼ぶ、 state machine は省略形のようです。

golangでのFSM

https://github.com/looplab/fsm
今回使ったライブラリは上のものです。

nodeの生成

const (
        start  = "start"
        middle = "middle"
        end    = "end"
        finish = ""
    )

    eventTree := fsm.Events{
        {
            Name: start,
            Src:  []string{start},
            Dst:  middle,
        },
        {
            Name: middle,
            Src:  []string{start},
            Dst:  end,
        },
        {
            Name: end,
            Src:  []string{end,start},
            Dst:  finish,
        },
        {
            Name: finish,
            Src:  []string{finish,middle},
            Dst:  finish,
        },
    }

このライブラリはEventという単位で遷移イベントを定義します。
それぞれ、


* Src : 遷移元のnode
* Dst : 遷移先のnode

となります。

state machine の生成

Eventを定義したら、state machineを生成します。
* 初期node名
* 全体のnodeの配列
* コールバック関数(特定のタイミング処理を実行できるもの、今回は省略)

    ownFsm := fsm.NewFSM(
        start,
        eventTree,
        fsm.Callbacks{},
    )

これでstate machineを生成できます。
あとは初期nodeから遷移可能なnodeを指定すると遷移できます。

ownFsm.Current() // start 
ownFsm.Event(start) // start eventが発火し、Dstのnodeへ遷移
ownFsm.Current() // middle

可視化

この構造を頭の中で毎回書くのは非常にしんどいです。
しかし、このライブラリは、state machine を可視化する機能がついています。

fsm.VisualizeWithType(ownFsm,fsm.GRAPHVIZ)

こんな形で、state machineと可視化方式を指定すると、

digraph fsm {
    "middle" -> "finish" [ label = "finish" ];
    "end" -> "finish" [ label = "end" ];
    "finish" -> "finish" [ label = "finish" ];
    "start" -> "finish" [ label = "end" ];
    "start" -> "end" [ label = "middle" ];
    "start" -> "middle" [ label = "start" ];

    "end";
    "finish";
    "middle";
    "start";
}

可視化のフォーマットに対応した、テキストを生成してくれます。
今回の場合は graphvizを指定したので、
http://www.webgraphviz.com/

上記で生成されたテキストを貼り付けて、generateすると可視化されます。

今回だとこんな感じ

  • Name : イベントスクリーンショット 2021-07-18 0.55.14.png

Eventは矢印の遷移の部分を指しています。

最後に

チャットボットで利用する際は、初期位置を変えたstate machineを毎回生成して、Eventを呼び出せばいけそうなのでは?と雑に考えてました。

それでは良いstate machine ライフを。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What is going on with this article?