goroutine:可以理解为一个轻量的线程,语法:go 函数名()
channel:中文为“通道”,可以理解为一个管,一端进行接数据,另一端收数据。语法:c:=make(chan int)。通道需要有接收和发送。
关于goroutine与channel的组合使用,见如下2个例子。
例1:channel通信
1 func sum(a int,c chan int){ 2 num:=a+100 3 c <- num 4 } 5 6 func main(){ 7 c:=make(chan int) 8 go sum(100,c) 9 sum1:= <- c 10 fmt.Println(sum) 11 }
输出:>>>200
备注:
a.这段代码写了2个函数,sum()与main()通过channel通信,并且在main中使用goroutine开启一个线程。
b.sum()函数的参数有一个int和一个channel,且在第3行将函数的运行结果使用channel接收。在mian()函数中,channel的数据发送给变量sum1,以此实现channel通信的作用。
c.在第8行,通过go开始了一个协程,如果去掉go就相当于没有开启协程,会出现dead lock。或者修改第7行第8行如下:
... c:=make(chan int,1) sum1(100,c) ...
修改后的c在make时就定义了一个缓冲区,缓冲区的大小为1,缓冲区可以理解为队列长度。运行时超出队列长度也会报错。
例2:channel的通知作用
1 var complete chan int =make(chan int) 2 3 func loop(){ 4 for i:=0;i<10;i++{ 5 fmt.Printf("%d ",i) 6 } 7 complete <- 0 8 } 9 10 func main(){ 11 go loop() 12 // loop() 13 <- complete
结果:>>>0 1 2 3 4 5 6 7 8 9
备注:
a.这段代码主要是描述channel的通知作用:main函数的 <- complete 其实就是阻塞住main线不让main线过早跑完,直到main线从complete中读出消息(0)
b.第11行和第12行,loop()被调用2次,第一次是roroutine开启的线程,第二次是main()开启的。而main()退出比较快,它执行完了goroutine还未来得及执行。或者可以在12行后加一个延迟(time.Sleep(time.Second)),加了之后两个线程都可以执行、
c.第7行体现了channel的通知作用:当loop()函数体执行完毕后,会发消息给channel,消息是0;在第13行,如果取到了消息(0)则说明goroutine的线程跑完了,否则mian()会阻塞住。