prime filter
使用并发来做一个素数筛
package main
import "fmt"
func main() {
ch :=GenerateNatural()
for i:=0;i<100;i++{
prime := <-ch // 第一个一定是素数
fmt.Printf("%v: %v\n", i+1, prime)
ch = primeFliter(ch,prime)
}
}
// 生成一个自然数列
func GenerateNatural() chan int {
ch := make(chan int)
go func() {
for i := 2; ; i++ {
ch <- i
}
}()
return ch
}
// 根据prime过滤,过滤后的第一个一定是素数
func primeFliter(in <- chan int,prime int) chan int{
out := make(chan int)
go func() {
for {
if i:=<-in;i%prime!=0{
out <- i
}
}
}()
return out
}
GenerateNatural和PrimeFilter函数内部都启动了新的Goroutine,当main函数不再使用管道时后台Goroutine有泄漏的风险。可以通过context包来避免这个问题,下面是改进的素数筛实现:
package main
import (
"context"
"fmt"
)
func GenerateNatural(ctx context.Context) chan int {
ch := make(chan int)
go func() {
for i := 2; ; i++ {
select {
case <-ctx.Done():
return
case ch <- i:
}
}
}()
return ch
}
func primeFilter(ctx context.Context, in <-chan int, prime int) chan int {
out := make(chan int)
go func() {
for {
if i := <-in; i%prime != 0 {
select {
case <-ctx.Done():
return
case out <- i:
}
}
}
}()
return out
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
ch := GenerateNatural(ctx)
for i := 0; i < 1000; i++ {
prime := <-ch
fmt.Printf("%v: %v\n", i+1, prime)
ch = primeFilter(ctx, ch, prime)
}
cancel() // main函数完成时,调用cancel(),通知后台goroutine退出,即ctx.Done收到信号
}