算法原理
参考自今日头条Go建千亿级微服务的实践 举出的goroutine例子
代码
//参数n, 找到(0,n)以内的素数
func get_prime(n int) {
origin, wait := make(chan int), make(chan struct{})
go FilterPrime(origin, wait)
for i := 2; i <= n; i++ {
origin <- i
}
close(origin)
<-wait #等待同步 防止主线程退出
}
func FilterPrime(seq chan int, wait chan struct{}) {
prime, ok := <-seq
if !ok {
close(wait)
return
}
fmt.Println(prime) //打印素数
out := make(chan int)
go FilterPrime(out, wait) //启动另一个goroutine
for num := range seq {
if num%prime != 0 {
out <- num
}
}
close(out)
}
测试
package main
import (
"fmt"
)
func main() {
get_prime(10)
}
输出
[ `go run my_prime.go` | done: 5.4524181s ]
2
3
5
7
Tips: wait变量等待同步
测试代码
```go
package main
import (
"fmt"
"time"
)
func main() {
wait := make(chan struct{})
go sleepawhile(wait)
fmt.Println("try to wait")
<-wait //注释后异常
fmt.Println("wait Done")
}
func sleepawhile(wait chan struct{}) {
fmt.Println("go to sleep")
time.Sleep(3 * time.Second)
fmt.Println("sleep Done")
fmt.Println("try to close wait")
close(wait)
fmt.Println("close wait Done")
return
}
正常输出:
try to wait
go to sleep
sleep Done
try to close wait
close wait Done
wait Done
若注释掉 main函数中的"<-wait" 输出:
try to wait
wait Done
未等待其他协程运行, 主线程已退出.
channel设置缓冲区
上文中用到的chan都没有缓冲区, 设置缓冲区之后, 一定范围内性能优化明显
package main
import (
"fmt"
"time"
)
func main() {
testSize := []int{1, 5, 10, 20, 30, 50, 70, 80, 100,200}
for _, size := range testSize{
var sum int64
for t := 0; t< 10; t++{
sum = sum + Prime(10000, size)
}
fmt.Printf("size:%d avg: %d ms \n",size,sum/10)
}
}
func Prime(n int, size int) int64 {
start := time.Now()
seq, wait := make(chan int, size), make(chan struct{})
go PrimeFilter(seq, wait, size)
for i := 2; i<= n; i++{
seq <- i
}
close(seq)
<- wait
timeConsumed := time.Since(start).Nanoseconds()/1000000
//fmt.Printf("time consumed: %v \n",timeConsumed)
return timeConsumed
}
func PrimeFilter(seq chan int, wait chan struct{}, size int) {
prime, ok := <- seq
if !ok {
close(wait)
return
}
//fmt.Println(prime)
next := make(chan int, size)
go PrimeFilter(next, wait, size)
for num := range seq{
if num%prime != 0{
next <- num
}
}
close(next)
}
输出:
size:1 avg: 37 ms
size:5 avg: 25 ms
size:10 avg: 23 ms
size:20 avg: 19 ms
size:30 avg: 18 ms
size:50 avg: 17 ms
size:70 avg: 18 ms
size:80 avg: 19 ms
size:100 avg: 16 ms
size:200 avg: 20 ms