欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言狀態(tài)機(jī)的實(shí)現(xiàn)

 更新時(shí)間:2023年03月09日 11:20:57   作者:棉花糖灬  
本文主要介紹了Go語言狀態(tài)機(jī)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、狀態(tài)機(jī)

1. 定義

有限狀態(tài)機(jī)(Finite-state machine, FSM),簡稱狀態(tài)機(jī),是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動作等行為的數(shù)學(xué)模型。

2. 組成要素

  • 現(xiàn)態(tài)(src state):事務(wù)當(dāng)前所處的狀態(tài)。
  • 事件(event):事件就是執(zhí)行某個(gè)操作的觸發(fā)條件,當(dāng)一個(gè)事件被滿足,將會觸發(fā)一個(gè)動作,或者執(zhí)行一次狀態(tài)的遷移。
  • 動作(action):事件滿足后執(zhí)行的動作。動作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動作不是必需的,當(dāng)事件滿足后,也可以不執(zhí)行任何動作,直接遷移到新狀態(tài)。
  • 次態(tài)(dst state):事件滿足后要遷往的新狀態(tài)。“次態(tài)”是相對于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。
  • 狀態(tài)流轉(zhuǎn)(transition):事物從現(xiàn)態(tài)轉(zhuǎn)為次態(tài)的整個(gè)過程。

3. 優(yōu)點(diǎn)

  • 代碼抽象:將業(yè)務(wù)流程進(jìn)行抽象和結(jié)構(gòu)化,將復(fù)雜的狀態(tài)轉(zhuǎn)移圖,分割成相鄰狀態(tài)的最小單元。這樣相當(dāng)于搭建樂高積木,在這套機(jī)制上可以組合成復(fù)雜的狀態(tài)轉(zhuǎn)移圖,同時(shí)隱藏了系統(tǒng)的復(fù)雜度。
  • 簡化流程:業(yè)務(wù)rd只需要關(guān)注當(dāng)前操作的業(yè)務(wù)邏輯(狀態(tài)流轉(zhuǎn)過程中的業(yè)務(wù)回調(diào)函數(shù)),極大的解耦了狀態(tài)和業(yè)務(wù)。
  • 易擴(kuò)展:在新增狀態(tài)或事件時(shí),無需修改原有的狀態(tài)流轉(zhuǎn)邏輯,直接建立新的狀態(tài)轉(zhuǎn)移鏈路即可。
  • 業(yè)務(wù)建模:通過最小粒度的相鄰狀態(tài)拼接,最終組成了業(yè)務(wù)的整體graph。

二、代碼

假設(shè)我們有要實(shí)現(xiàn)一個(gè)訂單下單功能,上圖是訂單狀態(tài)的流轉(zhuǎn)圖,方框?yàn)橛唵蔚臓顟B(tài),箭頭旁的文字為事件。

1. database包

package database

import "fmt"

// DB 模擬數(shù)據(jù)庫對象
type DB struct {
}

// Transaction 模擬事務(wù)
func (db *DB) Transaction(fun func() error) error {
?? ?fmt.Println("事務(wù)執(zhí)行開始。")
?? ?err := fun()
?? ?fmt.Println("事務(wù)執(zhí)行結(jié)束。")
?? ?return err
}

// Order 訂單
type Order struct {
?? ?ID ? ?int64 // 主鍵ID
?? ?State int ? // 狀態(tài)
}

type OrderList []*Order

// 查詢所有訂單
func ListAllOrder() (OrderList, error) {
?? ?orderList := OrderList{
?? ??? ?&Order{1, 0},
?? ??? ?&Order{2, 1},
?? ??? ?&Order{2, 2},
?? ?}
?? ?return orderList, nil
}

// UpdateOrderState 更新訂單狀態(tài)
func UpdateOrderState(curOrder *Order, srcState int, dstState int) error {
?? ?if curOrder.State == srcState {
?? ??? ?curOrder.State = dstState
?? ?}
?? ?fmt.Printf("更新id為 %v 的訂單狀態(tài),從現(xiàn)態(tài)[%v]到次態(tài)[%v]\n", curOrder.ID, srcState, dstState)
?? ?return nil
}

用來模擬數(shù)據(jù)庫的操作,如數(shù)據(jù)庫事務(wù)、查詢所有訂單、更新訂單狀態(tài)等。

2. fsm包

package fsm

import (
?? ?"fmt"
?? ?"reflect"
?? ?"zuzhiang/database"
)

// FSMState 狀態(tài)機(jī)的狀態(tài)類型
type FSMState int

// FSMEvent 狀態(tài)機(jī)的事件類型
type FSMEvent string

// FSMTransitionMap 狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移圖類型,現(xiàn)態(tài)和事件一旦確定,次態(tài)和動作就唯一確定
type FSMTransitionMap map[FSMState]map[FSMEvent]FSMDstStateAndAction

// FSMTransitionFunc 狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移函數(shù)類型
type FSMTransitionFunc func(params map[string]interface{}, srcState FSMState, dstState FSMState) error

// FSMDstStateAndAction 狀態(tài)機(jī)的次態(tài)和動作
type FSMDstStateAndAction struct {
?? ?DstState FSMState ?// 次態(tài)
?? ?Action ? FSMAction // 動作
}

// FSMAction 狀態(tài)機(jī)的動作
type FSMAction interface {
?? ?Before(bizParams map[string]interface{}) error ? ? ? ? ? ? ? ? ? // 狀態(tài)轉(zhuǎn)移前執(zhí)行
?? ?Execute(bizParams map[string]interface{}, tx *database.DB) error // 狀態(tài)轉(zhuǎn)移中執(zhí)行
?? ?After(bizParams map[string]interface{}) error ? ? ? ? ? ? ? ? ? ?// 狀態(tài)轉(zhuǎn)移后執(zhí)行
}

// FSM 狀態(tài)機(jī),元素均為不可導(dǎo)出
type FSM struct {
?? ?transitionMap ?FSMTransitionMap ?// 狀態(tài)轉(zhuǎn)移圖
?? ?transitionFunc FSMTransitionFunc // 狀態(tài)轉(zhuǎn)移函數(shù)
}

// CreateNewFSM 創(chuàng)建一個(gè)新的狀態(tài)機(jī)
func CreateNewFSM(transitionFunc FSMTransitionFunc) *FSM {
?? ?return &FSM{
?? ??? ?transitionMap: ?make(FSMTransitionMap),
?? ??? ?transitionFunc: transitionFunc,
?? ?}
}

// SetTransitionMap 設(shè)置狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移圖
func (fsm *FSM) SetTransitionMap(srcState FSMState, event FSMEvent, dstState FSMState, action FSMAction) {
?? ?if int(srcState) < 0 || len(event) <= 0 || int(dstState) < 0 {
?? ??? ?panic("現(xiàn)態(tài)|事件|次態(tài)非法。")
?? ??? ?return
?? ?}
?? ?transitionMap := fsm.transitionMap
?? ?if transitionMap == nil {
?? ??? ?transitionMap = make(FSMTransitionMap)
?? ?}
?? ?if _, ok := transitionMap[srcState]; !ok {
?? ??? ?transitionMap[srcState] = make(map[FSMEvent]FSMDstStateAndAction)
?? ?}
?? ?if _, ok := transitionMap[srcState][event]; !ok {
?? ??? ?dstStateAndAction := FSMDstStateAndAction{
?? ??? ??? ?DstState: dstState,
?? ??? ??? ?Action: ? action,
?? ??? ?}
?? ??? ?transitionMap[srcState][event] = dstStateAndAction
?? ?} else {
?? ??? ?fmt.Printf("現(xiàn)態(tài)[%v]+事件[%v]+次態(tài)[%v]已定義過,請勿重復(fù)定義。\n", srcState, event, dstState)
?? ??? ?return
?? ?}
?? ?fsm.transitionMap = transitionMap
}

// Push 狀態(tài)機(jī)的狀態(tài)遷移
func (fsm *FSM) Push(tx *database.DB, params map[string]interface{}, currentState FSMState, event FSMEvent) error {
?? ?// 根據(jù)現(xiàn)態(tài)和事件從狀態(tài)轉(zhuǎn)移圖獲取次態(tài)和動作
?? ?transitionMap := fsm.transitionMap
?? ?events, eventExist := transitionMap[currentState]
?? ?if !eventExist {
?? ??? ?return fmt.Errorf("現(xiàn)態(tài)[%v]未配置遷移事件", currentState)
?? ?}
?? ?dstStateAndAction, ok := events[event]
?? ?if !ok {
?? ??? ?return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]未配置次態(tài)", currentState, event)
?? ?}
?? ?dstState := dstStateAndAction.DstState
?? ?action := dstStateAndAction.Action

?? ?// 執(zhí)行before方法
?? ?if action != nil {
?? ??? ?fsmActionName := reflect.ValueOf(action).String()
?? ??? ?fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].before\n", currentState, event, dstState, fsmActionName)
?? ??? ?if err := action.Before(params); err != nil {
?? ??? ??? ?return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v]失敗, [%v].before, err: %v", currentState, event, dstState, fsmActionName, err)
?? ??? ?}
?? ?}

?? ?// 事務(wù)執(zhí)行execute方法和transitionFunc
?? ?if tx == nil {
?? ??? ?tx = new(database.DB)
?? ?}
?? ?transactionErr := tx.Transaction(func() error {
?? ??? ?fsmActionName := reflect.ValueOf(action).String()
?? ??? ?fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].execute\n", currentState, event, dstState, fsmActionName)
?? ??? ?if action != nil {
?? ??? ??? ?if err := action.Execute(params, tx); err != nil {
?? ??? ??? ??? ?return fmt.Errorf("狀態(tài)轉(zhuǎn)移執(zhí)行出錯(cuò):%v", err)
?? ??? ??? ?}
?? ??? ?}

?? ??? ?fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], transitionFunc\n", currentState, event, dstState)
?? ??? ?if err := fsm.transitionFunc(params, currentState, dstState); err != nil {
?? ??? ??? ?return fmt.Errorf("執(zhí)行狀態(tài)轉(zhuǎn)移函數(shù)出錯(cuò): %v", err)
?? ??? ?}
?? ??? ?return nil
?? ?})
?? ?if transactionErr != nil {
?? ??? ?return transactionErr
?? ?}

?? ?// 執(zhí)行after方法
?? ?if action != nil {
?? ??? ?fsmActionName := reflect.ValueOf(action).String()
?? ??? ?fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].after\n", currentState, event, dstState, fsmActionName)
?? ??? ?if err := action.After(params); err != nil {
?? ??? ??? ?return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v]失敗, [%v].before, err: %v", currentState, event, dstState, fsmActionName, err)
?? ??? ?}
?? ?}
?? ?return nil
}

狀態(tài)機(jī)包含的元素有兩個(gè):狀態(tài)轉(zhuǎn)移圖和狀態(tài)轉(zhuǎn)移函數(shù),為了防止包外直接調(diào)用,這兩個(gè)元素都設(shè)為了不可導(dǎo)出的。狀態(tài)轉(zhuǎn)移圖說明了狀態(tài)機(jī)的狀態(tài)流轉(zhuǎn)情況,狀態(tài)轉(zhuǎn)移函數(shù)定義了在狀態(tài)轉(zhuǎn)移的過程中需要做的事情,在創(chuàng)建狀態(tài)時(shí)指定,如更新數(shù)據(jù)庫實(shí)體(order)的狀態(tài)。

而狀態(tài)轉(zhuǎn)移圖又包含現(xiàn)態(tài)、事件、次態(tài)和動作,一旦現(xiàn)態(tài)和事件確定,那么狀態(tài)流轉(zhuǎn)的唯一次態(tài)和動作就隨之確定。

狀態(tài)機(jī)的動作又包含三個(gè):Before、Execute和After。Before操作在是事務(wù)前執(zhí)行,由于此時(shí)沒有翻狀態(tài),所以該步可能會被重復(fù)執(zhí)行。Execute操作是和狀態(tài)轉(zhuǎn)移函數(shù)在同一事務(wù)中執(zhí)行的,同時(shí)成功或同時(shí)失敗。After操作是在事務(wù)后執(zhí)行,因?yàn)樵趫?zhí)行前狀態(tài)已經(jīng)翻轉(zhuǎn),所以最多會執(zhí)行一次,在業(yè)務(wù)上允許執(zhí)行失敗或未執(zhí)行。

狀態(tài)機(jī)的主要方法有兩個(gè),SetTransitionMap方法用來設(shè)置狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移圖,Push方法用來根據(jù)現(xiàn)態(tài)和事件推動狀態(tài)機(jī)進(jìn)行狀態(tài)翻轉(zhuǎn)。Push方法中會先執(zhí)行Before動作,再在同一事務(wù)中執(zhí)行Execute動作和狀態(tài)轉(zhuǎn)移函數(shù),最后執(zhí)行After動作。在執(zhí)行Push方法的時(shí)候會將params參數(shù)傳遞給狀態(tài)轉(zhuǎn)移函數(shù)。

3. order包

(1) order

package order

import (
?? ?"fmt"
?? ?"zuzhiang/database"
?? ?"zuzhiang/fsm"
)

var (
?? ?// 狀態(tài)
?? ?StateOrderInit ? ? ? ? ?= fsm.FSMState(0) // 初始狀態(tài)
?? ?StateOrderToBePaid ? ? ?= fsm.FSMState(1) // 待支付
?? ?StateOrderToBeDelivered = fsm.FSMState(2) // 待發(fā)貨
?? ?StateOrderCancel ? ? ? ?= fsm.FSMState(3) // 訂單取消
?? ?StateOrderToBeReceived ?= fsm.FSMState(4) // 待收貨
?? ?StateOrderDone ? ? ? ? ?= fsm.FSMState(5) // 訂單完成

?? ?// 事件
?? ?EventOrderPlace ? ? ?= fsm.FSMEvent("EventOrderPlace") ? ? ?// 下單
?? ?EventOrderPay ? ? ? ?= fsm.FSMEvent("EventOrderPay") ? ? ? ?// 支付
?? ?EventOrderPayTimeout = fsm.FSMEvent("EventOrderPayTimeout") // 支付超時(shí)
?? ?EventOrderDeliver ? ?= fsm.FSMEvent("EventOrderDeliver") ? ?// 發(fā)貨
?? ?EventOrderReceive ? ?= fsm.FSMEvent("EventOrderReceive") ? ?// 收貨
)

var orderFSM *fsm.FSM

// orderTransitionFunc 訂單狀態(tài)轉(zhuǎn)移函數(shù)
func orderTransitionFunc(params map[string]interface{}, srcState fsm.FSMState, dstState fsm.FSMState) error {
?? ?// 從params中解析order參數(shù)
?? ?key, ok := params["order"]
?? ?if !ok {
?? ??? ?return fmt.Errorf("params[\"order\"]不存在。")
?? ?}
?? ?curOrder := key.(*database.Order)
?? ?fmt.Printf("order.ID: %v, order.State: %v\n", curOrder.ID, curOrder.State)

?? ?// 訂單狀態(tài)轉(zhuǎn)移
?? ?if err := database.UpdateOrderState(curOrder, int(srcState), int(dstState)); err != nil {
?? ??? ?return err
?? ?}
?? ?return nil
}

// Init 狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移圖初始化
func Init() {
?? ?orderFSM = fsm.CreateNewFSM(orderTransitionFunc)
?? ?orderFSM.SetTransitionMap(StateOrderInit, EventOrderPlace, StateOrderToBePaid, PlaceAction{}) ? ? ? ? ? ? ? ? ?// 初始化+下單 -> 待支付
?? ?orderFSM.SetTransitionMap(StateOrderToBePaid, EventOrderPay, StateOrderToBeDelivered, PayAction{}) ? ? ? ? ? ? // 待支付+支付 -> 待發(fā)貨
?? ?orderFSM.SetTransitionMap(StateOrderToBePaid, EventOrderPayTimeout, StateOrderCancel, nil) ? ? ? ? ? ? ? ? ? ? // 待支付+支付超時(shí) -> 訂單取消
?? ?orderFSM.SetTransitionMap(StateOrderToBeDelivered, EventOrderDeliver, StateOrderToBeReceived, DeliverAction{}) // 待發(fā)貨+發(fā)貨 -> 待收貨
?? ?orderFSM.SetTransitionMap(StateOrderToBeReceived, EventOrderReceive, StateOrderDone, ReceiveAction{}) ? ? ? ? ?// 待收貨+收貨 -> 訂單完成
}

// ExecOrderTask 執(zhí)行訂單任務(wù),推動狀態(tài)轉(zhuǎn)移
func ExecOrderTask(params map[string]interface{}) error {
?? ?// 從params中解析order參數(shù)
?? ?key, ok := params["order"]
?? ?if !ok {
?? ??? ?return fmt.Errorf("params[\"order\"]不存在。")
?? ?}
?? ?curOrder := key.(*database.Order)

?? ?// 初始化+下單 -> 待支付
?? ?if curOrder.State == int(StateOrderInit) {
?? ??? ?if err := orderFSM.Push(nil, params, StateOrderInit, EventOrderPlace); err != nil {
?? ??? ??? ?return err
?? ??? ?}
?? ?}
?? ?// 待支付+支付 -> 待發(fā)貨
?? ?if curOrder.State == int(StateOrderToBePaid) {
?? ??? ?if err := orderFSM.Push(nil, params, StateOrderToBePaid, EventOrderPay); err != nil {
?? ??? ??? ?return err
?? ??? ?}
?? ?}
?? ?// 待支付+支付超時(shí) -> 訂單取消
?? ?if curOrder.State == int(StateOrderToBePaid) {
?? ??? ?if err := orderFSM.Push(nil, params, StateOrderToBePaid, EventOrderPayTimeout); err != nil {
?? ??? ??? ?return err
?? ??? ?}
?? ?}
?? ?// 待發(fā)貨+發(fā)貨 -> 待收貨
?? ?if curOrder.State == int(StateOrderToBeDelivered) {
?? ??? ?if err := orderFSM.Push(nil, params, StateOrderToBeDelivered, EventOrderDeliver); err != nil {
?? ??? ??? ?return err
?? ??? ?}
?? ?}
?? ?// 待收貨+收貨 -> 訂單完成
?? ?if curOrder.State == int(StateOrderToBeReceived) {
?? ??? ?if err := orderFSM.Push(nil, params, StateOrderToBeReceived, EventOrderReceive); err != nil {
?? ??? ??? ?return err
?? ??? ?}
?? ?}
?? ?return nil
}

order包中做的事情主要有:

  • 定義訂單狀態(tài)機(jī)的狀態(tài)和事件;
  • 創(chuàng)建一個(gè)狀態(tài)機(jī),并設(shè)置狀態(tài)轉(zhuǎn)移函數(shù)和狀態(tài)轉(zhuǎn)移圖;
  • 執(zhí)行訂單任務(wù),推動狀態(tài)轉(zhuǎn)移。

(2) order_action_place

package order

import (
?? ?"fmt"
?? ?"zuzhiang/database"
)

type PlaceAction struct {
}

// Before 事務(wù)前執(zhí)行,業(yè)務(wù)上允許多次操作
func (receiver PlaceAction) Before(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行下單的Before方法。")
?? ?return nil
}

// Execute 事務(wù)中執(zhí)行,與狀態(tài)轉(zhuǎn)移在同一事務(wù)中
func (receiver PlaceAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {
?? ?fmt.Println("執(zhí)行下單的Execute方法。")
?? ?return nil
}

// After 事務(wù)后執(zhí)行,業(yè)務(wù)上允許執(zhí)行失敗或未執(zhí)行
func (receiver PlaceAction) After(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行下單的After方法。")
?? ?return nil
}

(2) ~ (5)是訂單不同動作的聲明和實(shí)現(xiàn)。

(3) order_action_pay

package order

import (
?? ?"fmt"
?? ?"zuzhiang/database"
)

type PayAction struct {
}

// Before 事務(wù)前執(zhí)行,業(yè)務(wù)上允許多次操作
func (receiver PayAction) Before(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行支付的Before方法。")
?? ?return nil
}

// Execute 事務(wù)中執(zhí)行,與狀態(tài)轉(zhuǎn)移在同一事務(wù)中
func (receiver PayAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {
?? ?fmt.Println("執(zhí)行支付的Execute方法。")
?? ?return nil
}

// After 事務(wù)后執(zhí)行,業(yè)務(wù)上允許執(zhí)行失敗或未執(zhí)行
func (receiver PayAction) After(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行支付的After方法。")
?? ?return nil
}

(4) order_action_deliver

package order

import (
?? ?"fmt"
?? ?"zuzhiang/database"
)

type DeliverAction struct {
}

// Before 事務(wù)前執(zhí)行,業(yè)務(wù)上允許多次操作
func (receiver DeliverAction) Before(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行發(fā)貨的Before方法。")
?? ?return nil
}

// Execute 事務(wù)中執(zhí)行,與狀態(tài)轉(zhuǎn)移在同一事務(wù)中
func (receiver DeliverAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {
?? ?fmt.Println("執(zhí)行發(fā)貨的Execute方法。")
?? ?return nil
}

// After 事務(wù)后執(zhí)行,業(yè)務(wù)上允許執(zhí)行失敗或未執(zhí)行
func (receiver DeliverAction) After(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行發(fā)貨的After方法。")
?? ?return nil
}

(5) order_action_receive

package order

import (
?? ?"fmt"
?? ?"zuzhiang/database"
)

type ReceiveAction struct {
}

// Before 事務(wù)前執(zhí)行,業(yè)務(wù)上允許多次操作
func (receiver ReceiveAction) Before(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行收貨的Before方法。")
?? ?return nil
}

// Execute 事務(wù)中執(zhí)行,與狀態(tài)轉(zhuǎn)移在同一事務(wù)中
func (receiver ReceiveAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {
?? ?fmt.Println("執(zhí)行收貨的Execute方法。")
?? ?return nil
}

// After 事務(wù)后執(zhí)行,業(yè)務(wù)上允許執(zhí)行失敗或未執(zhí)行
func (receiver ReceiveAction) After(bizParams map[string]interface{}) error {
?? ?fmt.Println("執(zhí)行收貨的After方法。")
?? ?return nil
}

4. main包

package main

import (
?? ?"fmt"
?? ?"zuzhiang/database"
?? ?"zuzhiang/order"
)

func main() {
?? ?order.Init()
?? ?orderList, dbErr := database.ListAllOrder()
?? ?if dbErr != nil {
?? ??? ?return
?? ?}
?? ?for _, curOrder := range orderList {
?? ??? ?params := make(map[string]interface{})
?? ??? ?params["order"] = curOrder
?? ??? ?if err := order.ExecOrderTask(params); err != nil {
?? ??? ??? ?fmt.Printf("執(zhí)行訂單任務(wù)出錯(cuò):%v\n", err)
?? ??? ?}
?? ??? ?fmt.Println("\n\n")
?? ?}
}

最后在main包里先初始化一個(gè)訂單狀態(tài)機(jī),查詢所有訂單,并使用狀態(tài)機(jī)執(zhí)行訂單任務(wù),推動訂單狀態(tài)轉(zhuǎn)移。注意多個(gè)訂單可以用同一個(gè)狀態(tài)機(jī)來進(jìn)行狀態(tài)的遷移。

三、個(gè)人總結(jié)

為什么要使用狀態(tài)機(jī),我想主要是它可以對一個(gè)復(fù)雜的業(yè)務(wù)流程進(jìn)行模塊化拆分,使得代碼更為易讀。并且擴(kuò)展性更好,如果后續(xù)有新狀態(tài)加入,只需要在原來的基礎(chǔ)上進(jìn)行擴(kuò)展即可,甚至不需要了解整個(gè)業(yè)務(wù)流程。

其次,它將數(shù)據(jù)庫實(shí)體的狀態(tài)流轉(zhuǎn)進(jìn)行了模范化,避免了不同的開發(fā)人員在寫更新數(shù)據(jù)庫實(shí)體狀態(tài)代碼時(shí)可能導(dǎo)致的問題。

到此這篇關(guān)于Go語言狀態(tài)機(jī)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go語言狀態(tài)機(jī)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang gorm 計(jì)算字段和獲取sum()值的實(shí)現(xiàn)

    golang gorm 計(jì)算字段和獲取sum()值的實(shí)現(xiàn)

    這篇文章主要介紹了golang gorm 計(jì)算字段和獲取sum()值的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言strconv包實(shí)現(xiàn)字符串和數(shù)值類型的相互轉(zhuǎn)換

    Go語言strconv包實(shí)現(xiàn)字符串和數(shù)值類型的相互轉(zhuǎn)換

    這篇文章主要介紹了Go語言strconv包實(shí)現(xiàn)字符串和數(shù)值類型的相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 用Go+WebSocket快速實(shí)現(xiàn)一個(gè)chat服務(wù)

    用Go+WebSocket快速實(shí)現(xiàn)一個(gè)chat服務(wù)

    這篇文章主要介紹了用Go+WebSocket快速實(shí)現(xiàn)一個(gè)chat服務(wù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Golang實(shí)現(xiàn)smtp郵件發(fā)送的示例代碼

    Golang實(shí)現(xiàn)smtp郵件發(fā)送的示例代碼

    這篇文章主要為大家詳細(xì)介紹了Golang實(shí)現(xiàn)smtp郵件發(fā)送的相關(guān)知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 一文詳解如何使用Go語言生成二維碼

    一文詳解如何使用Go語言生成二維碼

    使用Go語言編程時(shí),生成任意內(nèi)容的二維碼是非常方便的,下面這篇文章主要給大家介紹了關(guān)于如何使用Go語言生成二維碼的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • go?variant底層原理深入解析

    go?variant底層原理深入解析

    這篇文章主要為大家介紹了go?variant底層原理深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 如何利用Golang寫出高并發(fā)代碼詳解

    如何利用Golang寫出高并發(fā)代碼詳解

    今天領(lǐng)導(dǎo)問起為什么用Golang,同事回答語法簡單,語言新,支持高并發(fā)。那高并發(fā)到底如何實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于如何利用Golang寫出高并發(fā)代碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Go??import _ 下劃線使用

    Go??import _ 下劃線使用

    這篇文章主要為大家介紹了Go??import下劃線_使用小技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Golang中函數(shù)(Function)和方法(Method)的區(qū)別詳解

    Golang中函數(shù)(Function)和方法(Method)的區(qū)別詳解

    在Golang中,大家必然會頻繁使用到函數(shù)(Function)和方法(Method),但是有的同學(xué)可能并沒有注意過函數(shù)和方法的異同點(diǎn),函數(shù)和方法都是用來執(zhí)行特定任務(wù)的代碼塊,雖然很相似,但也有很大的區(qū)別,所以本文將詳細(xì)講解函數(shù)和方法的定義以及它們的異同點(diǎn)
    2023-07-07
  • 一文詳解Golang中的errors包

    一文詳解Golang中的errors包

    在 Golang 中,errors 包是用于處理錯(cuò)誤的標(biāo)準(zhǔn)庫, errors 包提供的功能比較簡單,使用起來非常方便,接下來就具體講解一下 errors 包提供的幾個(gè)函數(shù),感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07

最新評論