失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 《mysql入门圣经》_Go圣经-学习笔记之并发循环

《mysql入门圣经》_Go圣经-学习笔记之并发循环

时间:2019-04-29 03:20:42

相关推荐

《mysql入门圣经》_Go圣经-学习笔记之并发循环

首先说一个,本来上一篇文章应该是, Go圣经-学习笔记之Channel和Goroutine。写了很长一段,结果被有道云笔记TMD坑惨了,服务掉了,不能拷贝,不能保存。这篇文章就丢了。如果以后有时间,我再补,最近比较忙,先把后面部分写完。

并发循环

func main() {

var count = 10

var mg = make(chan struct{}, count)

for i := 0; i < count; i++ {

go func() {

fmt.Printf("i=%d\n", i+1)

mg

}()

}

for i := 0; i < count; i++ {

}

close(mg)

return

}

在Go圣经-学习笔记之函数值那篇文章中,可以知道函数值是由函数体和引用环境构成的。所以上面的返回结果是在GoSched调用Goroutine后运行时的引用变量,所以这个打印值是不确定的,但是一般来说结果是11。在以后写雨痕老师的学习笔记时,我再来具体讲解。Go f()只是创建一个goroutine,只有Goroutine被GoSched调度后才能真实的运行在内核态,这个时候获取变量i时,就是这时内存i变量值。这里for循环运行结束后,10个goroutine还没来得及被调度,所以i值都是11。

func main() {

var count = 10

var mg = make(chan struct{}, count)

for i := 0; i < count; i++ {

go func() {

fmt.Printf("i=%d\n", i+1)

mg

}()

time.Sleep(3 * time.Second) // main goroutine sleep 3s

}

for i := 0; i < count; i++ {

}

close(mg)

return

}

每执行一次for循环,main goroutine休息3s,则其他goroutine肯定会被GoSched调度,所以这个时候,打印值分别是:1,2,3,4,..., 10

改进一

如果你不想把变量i放在引用环境中,另一种方法

func main() {

var count = 10

var mg = make(chan struct{}, count)

for i := 0; i < count; i++ {

go func(i int) {

fmt.Printf("i=%d\n", i+1)

mg

}(i)

}

for i := 0; i < count; i++ {

}

close(mg)

return

}

改进二

如果goroutine执行过程中发生了错误,需要把错误信息汇总到一个指定的goroutine,可以使用channel来实现。

func main() {

var (

count = 10

errs = make(chan error, count)

wg =new(sync.WaitGroup)

)

wg.Add(count)

go processErrors(errs)

for i := 0; i < count; i++ {

go func(i int, errs chan err) {

wg.Done()

err := fmt.Errorf("error %d.", i+1)

errs

}(i, errs)

}

wg.Wait()

close(errs)

return

}

func processErrors(errs

for err := range errs{

fmt.Println(err.Error())

}

return

}

这里要说明的一点是:channel的两端发送者和接受者goroutine都不能一直阻塞下去,如果一直阻塞那就是goroutine泄露。

如果觉得《《mysql入门圣经》_Go圣经-学习笔记之并发循环》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。