goroutine的使用与常见错误

goroutine的使用时常见错误

goroutine是Golang 的核心之一,在使用时,一般都要配合channel一起使用。

在使用时,经常会遇到一些错误,包括:

  1. 不输出
  2. 输出与希望输出不一致
  3. all goroutines are asleep - deadlock!

对于error1,举个例子

func main() {
	for i := 0; i < 3; i++ {
		go func() {
			fmt.Printf("f1:%d\n", i)
		}()
	}
}

我们使用go func()创建了三个routine,但是发现没有输出。

原因:

3个routine刚被创建完成,进程就结束了

解决:

我在main进程中设置了res := <-a来等待三个routine分别发信号,只有发完信号,3个routine才能结束

func main() {
	a := make(chan int)
	for i := 0; i < 3; i++ {
		go func() {
			a <- i
		}()
	}
	for {
		res := <-a
		fmt.Printf("f1:%d\n", res)
	}
	close(a)
}

到目前为止,输出问题解决了,但是此时我们发现error2和error3都出来了

对于error2

到目前为止,我们发现,我们的输出为

f1:3
f1:3
f1:3

并非我们希望输出的f1:0 f1:1 f1:2

原因:

3个routine先被创建了,创建完后,执行routine内的内容,即读取i,然而此时i已经等于3,因此,读取时全部为3

解决:

变成go func(j int) {}(i),利用闭包函数传参

func main() {
	a := make(chan int)
	for i := 0; i < 3; i++ {
		go func(j int) {
			a <- j
		}(i)
	}
	for {
		res := <-a
		fmt.Printf("f1:%d\n", res)
	}
	close(a)
}

此时,我们发现已经解决了输出不正确的问题,但是此时all goroutines are asleep - deadlock!还在

对于error3

原因:3个routine都已经执行完毕,但是channel还在等待信号

解决方式:channel的send/receive数量对应即可

func main() {
	a := make(chan int)
	for i := 0; i < 3; i++ {
		go func(j int) {
			a <- j
		}(i)
	}
	for i := 0; i < 3; i++ {
		res := <-a
		fmt.Printf("f1:%d\n", res)
	}
	close(a)
}
posted @ 2019-08-28 00:18  wangha  阅读(716)  评论(0编辑  收藏  举报