出来混总是要还的
最近在准备记录一个.NET Go核心能力的深度对比, 关于.NET/Go的异步实现总感觉没敲到点上。
async/await是.NET界老生常谈的话题,每至于此,状态机又是必聊的话题,但是状态机又是比较晦涩难懂的话题。
一线码农大佬\]在博客园2020年写的《[await,async 我要把它翻个底朝天,这回你总该明白了吧](https://link.juejin.cn?target=https%3A%2F%2Fwww.cnblogs.com%2Fhuangxincheng%2Fp%2F13558006.html "https://www.cnblogs.com/huangxincheng/p/13558006.html")》手把手实现了异步状态机,这篇文章很是经典, 但是评论区很多人还是在吐槽看不懂, 我也看的不是很懂。
以我浅薄的推测:
1. 一线大佬的知识体系太宽太深,有的验证点在文字之外,需要我们自己去确认。
2. 有些内容太细节,挖的太深,出不来。
3. 很多人不熟悉**状态机设计模式**, 导致看大佬文章,知其然不知其所以然。
> 我以前用Go语言演示了状态机: [我是状态机,有一颗永远骚动的机器引擎](https://link.juejin.cn?target=https%3A%2F%2Fwww.cnblogs.com%2FJulianHuang%2Fp%2F15304184.html "https://www.cnblogs.com/JulianHuang/p/15304184.html"), 当时有粉丝留言让用.NET 实现状态机, 这篇文章也算是对粉丝的喊话。
### 状态机:一颗永远骚动的机器引擎
状态机是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。看起来好像对象改变了它的类。
请仔细理解上面每一个字。
我们以自动售货机为例,为简化演示,我们假设自动售货机只有1种商品, 故自动售货机有`itemCount` 、`itemPrice` 2个属性
不考虑动作的前后相关性,自动售货机对外暴露4种行为:
* 给自动售货机加货 `addItem`
* 选择商品 `requestItem`
* 付钱 `insertMoney`
* 出货 `dispenseItem`
重点来了,当发生某种行为,自动售货机会进入如下4种状态之一, 并据此状态做出特定动作, 之后进入另外一种状态.....
* 有商品 `hasItem`
* 无商品 `noItem`
* 已经选好商品 `itemRequested`
* 已付钱 `hasMoney`

当对象可能处于多种不同的状态之一、根据传入的动作更改当前的状态, 继续接受后续动作,状态再次发生变化.....
这样的模式类比于机器引擎,周而复始的工作和状态转化,这也是状态机的定语叫"**机Machine**"的原因。
有了以上思路,我们尝试沟通UML 伪代码 
状态机设计模式的伪代码实现:
* 所谓的机器Machine维护了状态切换的上下文
* 机器对外暴露的行为,驱动机器的状态变更
* 机器到达特定的状态 只具备特定的行为,其他行为是不被允许的
Go版本的售货机(状态机设计模式)的源码,请参见原文[www.cnblogs.com/JulianHuang...](https://link.juejin.cn?target=https%3A%2F%2Fwww.cnblogs.com%2FJulianHuang%2Fp%2F15304184.html%25E3%2580%2582 "https://www.cnblogs.com/JulianHuang/p/15304184.html%E3%80%82")
### 对async/await贴脸开大
还是以一线码农大佬的异步下载为例:

编译器词法分析定位到async/await语法糖,就会为开发者生成状态机代码。
一个新出炉的状态机包含如下属性 :
 (1) 初始化的状态机,以async所在的函数名命名,示例状态机为`