用chan而不用共享变量实现actor,因其天然保障状态私有、消息驱动、无锁并发;actor须独占in chan,状态不可导出,仅通过send发送消息,newactor需启动goroutine运行死循环处理消息。

为什么用 chan 而不用共享变量来实现 Actor
因为 Go 的 Actor 模型本质不是“模拟 Erlang”,而是利用 chan + goroutine 天然达成「状态私有、消息驱动、无锁并发」——只要每个 Actor 自己独占一个 in chan Message,所有外部修改都必须走这个入口,就不可能出现竞态。
常见错误是:在 Actor 内部还暴露了 State 字段给外部读写,或者用 sync.Mutex 包裹状态更新。这等于绕开 Actor 原则,白搭了模型价值。
- Actor 的状态必须完全不可导出(首字母小写),只响应收到的
Message - 所有对外接口只能是
Send(msg Message)这种发消息方法,不能有GetState()或UpdateXxx() - 如果需要返回结果,用带应答字段的
Message+ 回调chan,而不是函数返回值
NewActor() 必须封装 goroutine 启动逻辑
Actor 不是被动等待被调用的对象,而是一个持续运行的协程;它的生命周期由自己管理。漏掉 go actor.run() 是最常踩的坑——表面看结构体建好了,实际啥也不处理。
-
run()方法里必须是死循环:for msg := range actor.in { actor.handle(msg) } - 不要用
select { case msg := 单次收消息就退出,那只是个“消息处理器”,不是 Actor - 关闭
actor.in通道是唯一合法的终止方式,别用 context.WithCancel 强杀 goroutine
func (a *Actor) run() {
for msg := range a.in {
a.handle(msg)
}
}
消息类型设计要避免接口泛化陷阱
用 interface{} 或空 Message 接口看似灵活,实则让编译器失去类型检查能力,运行时 panic 频发,且无法静态推导消息流向。
修正说明:1,实现真正的软件开源。2,安装界面的美化3,真正实现栏目的递归无限极分类。4,后台添加幻灯片图片的管理,包括添加,修改,删除等。5,修正添加新闻的报错信息6,修正网站参数的logo上传问题7,修正产品图片的栏目无限极分类8,修正投票系统的只能单选问题9,添加生成静态页功能10,添加缓存功能特点和优势1. 基于B/S架构,通过本地电脑、局域网、互联网皆可使用,使得企业的管理与业务不受地域
- 推荐用具体消息 struct,比如
type SpawnPlayerMsg struct{ ID int; Name string } - 如果真要多态,用可判别的 tag 字段 + switch,而不是靠接口断言
- 禁止在消息里塞闭包或函数值——它们会捕获外部变量,导致内存泄漏或状态错乱
缓冲通道选 make(chan T, 1) 还是 make(chan T, 0)
零缓冲通道(默认)更符合 Actor “接收即处理” 的语义,但容易阻塞发送方;有缓冲则解耦更彻底,但也掩盖背压问题。
立即学习“go语言免费学习笔记(深入)”;
- 内部 Actor 之间通信(如 supervisor → worker)建议用
make(chan Message, 1):既防丢消息,又不至于积压太多 - 外部输入入口(如 HTTP handler → Actor)必须用带缓冲的 channel,否则高并发请求会直接卡在
Send()上 - 缓冲大小不是越大越好:超过 100 容易掩盖下游处理瓶颈,也增加 OOM 风险
chan 自动解决,得靠显式的消息协议和约定,而不是寄希望于 channel 关闭能自动级联。









