初次体验golang中的rountine和channel

先看看下面的代码。其中reader函数是作为gorountine执行的,它从channel中反复读取一个整数并打印。主函数main启动reader之后执行循环将1-20逐个写入channel。

package main

import "fmt"

func main() {
	c := make(chan int)
	go reader(c)

	i := 1
	for i <= 20 {
		c <- i
		i++
	}
}

func reader(c chan int) {
	for {
		x := <-c
		fmt.Println("Read from channel, got ", x)
	}
}

注意这里的channel不带有缓冲,是阻塞的。上面的代码能够正常运行。这是因为虽然channel是阻塞的,但是reader这个gorountine会从channel读取,所以不会造成deadlock。 如果将将main函数改成这样,会造成死锁。

  i := 1
	for i <= 20 {
		c <- i
		i++
	}

	go reader(c)

运行时的结果类似这样

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
	/Users/foo/test6.go:11 +0x44

如果我们将channel更改成带有缓冲区的类型呢?

func main() {
	c := make(chan int, 20)

	i := 1
	for i <= 20 {
		c <- i
		i++
	}
  
	go reader(c)

如上我们设置缓冲区大小为20,刚好能够容纳1-20的测试数据。运行程序不会再报错。这里读者可以猜猜看如果缓冲区设置成小于20呢?读者自己试试看。 另外一个问题是虽然代码运行不会报错,但是我们看不到任何输出,因为main在reader还没有执行就结束了,聪明的读者,想想看如何解决这个问题?

通过上面的简单例子,你应该能够弄明白channel的阻塞,缓冲区的概念了吧!