Go 系列教程 —— 23. 缓冲信道和工作池(Buffered Channels and Worker Pools)

Noluye ·
初学者。感谢您提供的工作池的教程。确实是学到了! 但是初看您的教程简直可以用一脸懵逼来形容我自己。只有自己在打完代码执行后才能完全理解您的意思。我发现,如果将函数的书写顺序改变一下,应该可以更好地帮助其他初学者的理解其中的含义。 以下是我的拙见: 1. 写 do job 的工具函数 ``` // 完成工作的工具 func digits(number int) int ``` 2. 写 job 的派发函数 ``` // 发布 noOfJobs 个工作,等待工人接收工作 func allocate(noOfJobs int) ``` 3. 写 一个工人去接收 job 并完成的函数 ``` // 一个工人去接收工作,接收到工作之后就要完成工作 // 完成工作之后,将原本的工作内容及其结果写入到 results 信道中 func worker(wg *sync.WaitGroup) { ``` 4. 写 接收 job 完成结果的函数 ``` // 接收任务的结果 func result(done chan bool) ``` 5. 写 创建工作池的函数 ``` // 创建工作池 // 创建 noOfWorkers 个工人来接收任务 // 工人越多,完成任务就越快。没毛病吧 func createWorkerPool(noOfWorkers int) ```
#19
更多评论
func allocate(noOfJobs int) { for i := 0; i < noOfJobs; i++ { randomno := rand.Intn(999) job := Job{i, randomno} jobs <- job } close(jobs) } 如果for循环结束后,jobs里面的数据worker还来不及取走,这时执行到close,会不会导致works取数据失败?或者取不到足额的任务? 谢谢!!
#1
这里 `close` 和关闭文件的概念不同。 golang 里的 `close` 只是用于通知信道的接收方,所有数据都已经发送完毕,信道**没有真正关闭**。 若用 `for range` 接收数据时,对于关闭了的信道,会接收完剩下的有效数据,并退出循环。如果没有 `close` 提示数据发送完毕的话,`for range` 会接收完剩下所有有效数据后发生阻塞。 所以接收方 `worker` 是可以把 `jobs` 剩下的数据取走的。后面垃圾收集器会自动回收掉该信道的内存。 可以参见《[the go programming language](https://www.amazon.com/dp/0134190440/?tag=stackoverflow17-20)》的说法: > You needn't close every channel when you've finished with it. It's only necessary to close a channel when it is important to tell the receiving goroutines that all data have been sent. A channel that the garbage collector determinies to be unreachable will have its resources reclaimed whether or not it is closed. (Don't confuse this with the close operation for open files. It is important to call the Close method on every file when you've finished with it.)
#2