golang 状态机
package main import (
"errors"
"fmt"
"reflect"
) type State interface {
Name() string
EnableSameTransit() bool
OnBegin()
OnEnd()
CanTransitTo(name string) bool
} func StateName(s State) string {
if s == nil{
return "none"
}
return reflect.TypeOf(s).Elem().Name()
} type StateInfo struct {
name string
} func (s *StateInfo) Name() string {
return s.name
}
func (s *StateInfo) setName(name string){
s.name = name
}
//是否能够同状态转移
func (s *StateInfo) EnableSameTransit()bool{
return false
}
func (s *StateInfo) OnBegin(){ }
func (s *StateInfo) OnEnd(){ }
//是否能够转移到状态
func (s *StateInfo) CanTransitTo(name string) bool{
return true
} type StateManager struct {
stateByName map[string]State
Onchange func(from,to State)
curr State
} func (sm *StateManager) Add(s State){
name := StateName(s)
s.(interface{
setName(name string)
}).setName(name)
if sm.Get(name)!=nil{
panic("重复添加:"+name)
}
sm.stateByName[name] = s
} func (sm *StateManager) Get(name string) State {
if v,ok:=sm.stateByName[name];ok{
return v
}
return nil
}
func NewStateManager()*StateManager{
return &StateManager{
stateByName:make(map[string]State),
}
}
var ErrForbidSameTransit = errors.New("ErrForbidSameTransit")
var ErrCannotTransitToState = errors.New("ErrCannotTransitToState")
var ErrStateNotFound = errors.New("ErrStateNotFound") func (sm *StateManager)CurrState()State {
return sm.curr
} func (sm *StateManager) CanCurrTransitTo(name string)bool {
if sm.curr == nil{
return true
}
if sm.curr.Name() == name && !sm.curr.EnableSameTransit(){
return true
}
return sm.curr.CanTransitTo(name)
}
func (sm *StateManager) Transit(name string)error{
next := sm.Get(name)
if next==nil{
return ErrStateNotFound
}
pre := sm.curr
if sm.curr!=nil{
if sm.curr.Name() == name && !sm.curr.EnableSameTransit(){
return ErrForbidSameTransit
}
if !sm.CanCurrTransitTo(name){
return ErrCannotTransitToState
}
sm.curr.OnEnd()
}
sm.curr = next
sm.curr.OnBegin()
if sm.Onchange!=nil{
sm.Onchange(pre,sm.curr)
}
return nil
} type IdleState struct {
StateInfo
} func (i *IdleState)OnBegin() {
fmt.Println("idle on begin")
}
func (i *IdleState)OnEnd() {
fmt.Println("idle on end")
} type MoveState struct {
StateInfo
} func (i *MoveState)OnBegin() {
fmt.Println("move on begin")
}
func (i *MoveState)OnEnd() {
fmt.Println("move on end")
} func (i *MoveState)EnableSameTransit() bool {
return true
} type JumpState struct {
StateInfo
} func (i *JumpState)OnBegin() {
fmt.Println("jump on begin")
}
func (i *JumpState)OnEnd() {
fmt.Println("jump on end")
}
func (i *JumpState) CanTransitTo(name string) bool {
return name != "MoveState"
} func main() {
sm := NewStateManager()
sm.Onchange = func(from, to State) {
fmt.Println("from",from,"to",to)
}
sm.Add(new(IdleState))
sm.Add(new(JumpState))
sm.Add(new(MoveState))
sm.Transit("JumpState")
sm.Transit("IdleState")
sm.Transit("MoveState")
}
golang 状态机的更多相关文章
- golang开源项目qor快速搭建网站qor-example运行实践
最近想找几个基于Go语言开发的简单的开源项目学习下,分享给大家,github上有心人的收集的awesome-go项目集锦:github地址 发现一个Qor项目: Qor 是基于 Golang 开发的的 ...
- 消息/事件, 同步/异步/协程, 并发/并行 协程与状态机 ——从python asyncio引发的集中学习
我比较笨,只看用await asyncio.sleep(x)实现的例子,看再多,也还是不会. 已经在unity3d里用过coroutine了,也知道是“你执行一下,主动让出权限:我执行一下,主动让出权 ...
- Golang后台开发初体验
转自:http://blog.csdn.net/cszhouwei/article/details/37740277 补充反馈 slice 既然聊到slice,就不得不提它的近亲array,这里不太想 ...
- Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目
Golang优秀开源项目汇总(持续更新...)我把这个汇总放在github上了, 后面更新也会在github上更新. https://github.com/hackstoic/golang-open- ...
- 面试必问:Golang高阶-Golang协程实现原理
引言 实现并发编程有进程,线程,IO多路复用的方式.(并发和并行我们这里不区分,如果CPU是多核的,可能在多个核同时进行,我们叫并行,如果是单核,需要排队切换,我们叫并发) 进程和线程的区别 进程是计 ...
- 数据结构和算法(Golang实现)(6)简单入门Golang-并发、协程和信道
并发.协程和信道 Golang语言提供了go关键字,以及名为chan的数据类型,以及一些标准库的并发锁等,我们将会简单介绍一下并发的一些概念,然后学习这些Golang特征知识. 一.并发介绍 我们写程 ...
- 找工作面试题记录与参考资料(Golang/C++/计算机网络/操作系统/算法等)
记录下去年(2020年)找工作的面试题及参考资料. C++ 智能指针的实现原理 多态的实现原理[2] C++11/14/17新特性[3] 手写memcpy和memmove[4] 介绍下boost库 计 ...
- Golang, 以17个简短代码片段,切底弄懂 channel 基础
(原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...
- 说说Golang的使用心得
13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...
随机推荐
- CDOJ 1069 秋实大哥去打工 单调栈 下标处理
E - 秋实大哥去打工 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu Submit St ...
- Java虚拟机之JVM调节参数
-XX:+PrintGC 使用这个参数,虚拟机启动后,每次GC就会打印日志. -XX:+UseSerialGC 使用串行垃圾回收器. -XX:+PrintGCDetails 打印详细信息.包括各个区的 ...
- 根据linux自带的JDK,配置JAVA_HOME目录
在配置hadoop是,进行格式化hadoop的时候,出现找不到jdk 我用centos6.5是64位的, 发现本机有java ,就找了一下其位置 找到了jdk-1.7.0_75 which java ...
- 阿里知识储备之二——junit学习以及android单元测试
一,junit框架 http://blog.csdn.net/afeilxc/article/details/6218908 详细见这篇博客 juit目前已经可以和maven项目进行集成和测试,而且貌 ...
- angular 的跨域处理
angular 的跨域处理,由于不并不支持跨域处理,所以我们对他也是无可奈何,angular 的跨域处理,需要我们在服务器上进行处理,把请求的数据改成 * ,也就是,谁都可以请求数据: angular ...
- jquery自动播放音频文件
使用jquery自动播放音频文件 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- python - property 属性函数
Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情.在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter ...
- Vue知识整理8:条件、URL、点击
1.通过v-if实现对条件的判断和执行: 2.通过v-bind:href实现对url地址的绑定,其中url写在data中: 3.通过@click="click1"实现点击事件,其中 ...
- 初学单片机:Proteus介绍、Proteus与Keil联调(Windows10环境下)
Proteus是一个仿真软件,可以在里面设计电路并模拟测试,也可生成PCB的布线等等,反正就是强大的不行.初学单片机,除了开发板,这个仿真器就是一个很好的调式环境.软件安装信息: Proteus 8. ...
- Linux centos 解决"不在 sudoers 文件中。此事将被报告"的问题
第一部分讲解如何从普通用户到root用户 网上看了很多,其实就是执行 su root ,然后输入当前用户密码,这个时候可能报错 这个问题不大,执行一下提示的语句: abrt-auto-reportin ...