【发布时间】:2016-03-02 02:54:21
【问题描述】:
我是 Go 新手,我正在编写一个简单的 Web 应用程序。基本思路是这样的:
goroutine #1 是 HTTP 服务器
goroutine #2 是一个管理应用程序状态的函数。它需要定期轮询一些硬件的值,所以它需要在自己的线程中运行。
当用户发出 HTTP 请求时,服务器会向 state goroutine 请求更新的信息,然后返回一个 HTML 页面给客户端。
这一切都很好,除了一件事:目前有六种不同的可能信号由服务器发送并从状态线程返回,包括请求和响应通道,总共 12 个通道(我m 将添加至少一个或两个以上的信号)。可以合并一些信号,但其中许多是不同的类型。
正如我所说,它有效,但它变得相当丑陋。
看起来像这样:
main.go 包含用于实例化通道的声明:
// a shutdown signal
shutdown := make(chan bool)
// request the current state of a sensor
sensorRequest := make(chan string)
sensorResponse := make(chan Sensor)
// request the current state of ALL sensors
sensorListRequest := make(chan bool)
sensorListResponse := make(chan []Sensor)
// request the current state of the application (active or inactive)
statusRequest := make(chan bool)
statusResponse := make(chan bool)
// and a few more...
// start the "state manager" goroutine
go ManageState(shutdown, sensorRequest, sensorResponse, sensorListRequest, sensorListResponse, statusRequest, statusResponse)
// start the "HTTP server" goroutine
go ManageHTTP(shutdown, sensorRequest, sensorResponse, sensorListRequest, sensorListResponse, statusRequest, statusResponse)
所以,有几个问题:
是否需要有单独的请求和响应通道?鉴于请求和响应是不同的类型,我看不到在两个方向上使用相同通道的明显方法(这不是 hacky)。
我考虑将所有通道放入一个可以传递给所有 goroutine 的结构中,但我不确定这会带来什么真正的好处 - 它似乎并不比我更清楚现在做。
这样做的Go方式™是什么?
更新
感谢@kostya 和@Aedolon 建议使用sync.Mutex 锁定/解锁的全局状态。这实际上是我的第一种方法,但我遇到了一个严重的问题:我的 Mutex Lock() 调用在释放锁时随机无法解锁。此代码将在 Raspberry Pi 上运行,我怀疑某处存在错误(在我用来读取硬件状态的包中或 Go ARM 二进制文件中)。但在花了很多时间试图追踪问题之后,我决定尝试不同的方法。
无论如何,在阅读(多次)我应该“不要通过共享内存进行通信;而是通过通信来共享内存”(The Go Blog)之后,我决定尝试以这种方式实现它。现在我这样做了,我发现我喜欢这种方法:-)
【问题讨论】:
-
Go 是关于完成工作的,如果它有效,它就是 Go 的方式;-)。
-
kostya 的回答很好。不要过度设计和强迫你的程序用通道和 goroutine 做所有事情,认为这就是 Go Way。用互斥锁保护全局状态并没有错。这通常是完成工作的最简单、直接和有效的方法。如果您需要一个监视硬件更新的 goroutine,那么就拥有它并让它更新全局状态。
-
如果你有复制器,我建议提交一个关于 Lock() 调用无法解除阻塞的错误。