首页 > 技术文章 > go:goroutine与channel

jinziguang 2020-08-17 19:50 原文

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 \t",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()会阻塞住。

 

 

本文转载自:https://blog.csdn.net/HYZX_9987/article/details/97528721?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

推荐阅读