原文:
1. 需求
启动一个goroutine,将1-10000的数字放入chan中
启动4个goroutine从chan中读取数字,并计算是不是素数
是素数就讲结果放入结果chan中
最后遍历结果chan,打印素数集合
2. 思路
这道题思路很简单,首先明确一个点就是这个需求有三种类型的goroutine:
第一种类型就是生产者,它主要负责数据的生产;
第二种类型就是消费者,他主要负责消费数据做加工;
第三种类型就是main goroutine,他主要负责调度这些goroutine并且等待他们退出。
明确思路之后我们在深入分析下,这个需求需要三个chan:
第一个就是生产者和消费者之间的通信是需要一个chan的,这个chan就是生产者生产数字放到chan中,消费者从chan取出数字。
第二个就是消费者计算完素数之后结果得放入一个chan中,这个chan需要和main goroutine通信,因为main goroutine需要遍历打印这些素数;
最后一个就是main goroutine需要等待所有消费goroutine的退出,因为我不知道消费者什么时候结束,所以也需要一个chan和main goroutine通信。
因此这个需求需要三种类型的goroutine和三种类型的chan。
3.代码实现
package main
import (
"fmt"
)
func main() {
prochan := make(chan int, 10000)
primeChan := make(chan int, 5000)
exitChan := make(chan bool, 4)
// 1.produce num
go producer(prochan)
// 2.consume num
for i := 0; i < 4; i++ {
go consumer(prochan, primeChan, exitChan)
}
// 3.up a g to wait consumers over
go func() {
for i := 0; i < 4; i++ {
<- exitChan
}
close(primeChan)
}()
defer close(exitChan)
// 4.main goroutine print the result
for v := range primeChan {
fmt.Println("main goroutine recv prime number is: ", v)
}
fmt.Println("main goroutine is over.")
}
// producer
func producer(proChan chan int) {
fmt.Println("Producer goroutine 开始生产数据啦!")
for i := 1; i <= 10000; i++ {
proChan <- i
}
close(proChan)
fmt.Println("Producer goroutine 开始生产结束啦!")
}
// consumer
func consumer(proChan chan int, primeChan chan int, exitChan chan bool) {
fmt.Println("Consumer goroutine 开始消费数据啦!")
for{
// 1.get num
num, ok := <- proChan
if !ok {
break // producer closed chan
}
// 2.if is prime number, add to prime chan
if isPrimeNum(num) {
primeChan <- num
}
}
// 3.the g is over
exitChan <- true
fmt.Println("Consumer goroutine 退出啦!")
}
func isPrimeNum(num int) bool {
if num == 1 {return true}
for i := 2; i < num; i++ {
if num % i == 0 {return false}
}
return true
}
标签:goroutine,chan,素数,func,go,main
From: https://www.cnblogs.com/davis12/p/16996448.html