理解golang中的channel

channel是goroutine之间的通信机制。可以类比线程间的通信,线程间的通信有多种方式,比如线程上下文、共享内存、IPC通信、socket实现不同机器间的通信。

channel用起来很简单,绑定一个变量,一端往里塞,一端从里面取。我把它理解为接收端启动了一个类似HTTP服务器的东西,发送端往接收端的HTTP服务器发送一条get请求,接收端就收到了,可以解析拿到请求的参数再做要做事情。

如何创建一个channel?

ch := make(chan int) // 创建一个channel

channel是有类型的,int类型的channel就只能传输int类型的数据,想传输string类型的数据创建的时候需要改为 ch := make(chan string)

如何向channel发送数据?

ch <- 123  // 向int类型的channel发送数据123

如何从接收数据?

x = <- ch

或者也可以不要接受对象

<- ch

可以看出,不管是发送还是接收数据,用的都是 <- ,区别在于 <- 指向的对象是普通变量还是channel,如果是channel被指向就是给channel发送数据,如果是普通变量被指向就是从channel中取数据。

channel是可以带缓存的,我们前面创建的channel是没带缓存的。有缓存和无缓存有什么区别吗?

缓存的存在是为了抹平channel发送端和接收端速度不匹配造成的资源浪费。比方说一个人扔苹果,一个人接苹果,扔的人扔的速度比接的人速度快,这时候苹果就会掉到地上了。如果没有缓存,我们该如何解决这个问题?

可以用阻塞的方式来解决。比方说我们约定,扔苹果的人在接苹果的人没有接到苹果之前,不能继续扔苹果了,要等到接苹果的人接到苹果才可以继续。这就是阻塞。

在无缓存的情况下,channel发送端在发送后会阻塞,直到发送的数组在channel里被别人接收了才可以继续。反过来如果接收操作先发生,那么接收端会被阻塞,直到它等到channel里传来的数据才恢复。

可以看出,在无缓存的情况下,channel之间的通信是同步的,一个等一个。缓存的出现让channel摆脱了同步,变成了异步的形式。

还是刚刚扔苹果的例子,扔苹果的速度比接苹果的速度快,这次接苹果的人在脚下放了一个框,说“这个框可以装10个苹果,你把苹果都扔到这个框里,我慢慢取。当然如果框里已经有10个苹果的时候,就不能再扔了,只能等到我取出苹果以后再扔。”

这样发送者和接收者的速度差就被缓存减小了一部分,我可以多来一个接收者从框里取苹果来加快接收端的速度。

如何创建一个待缓存的channel?

ch := make(chan int, 10)  // 创建一个可以存放10个int型数据的channel

  

channnel也可以关闭,关闭以后对这个channel的任何发送操作都会导致panic异常,但是还可以从这个channel中接收数据,如果channel里还有之前成功发送的数据,是可以取到的,但是如果channel已经空了,那就将返回一个零值。

关闭channel可以用

close(ch)  // 关闭channel

  

猜你喜欢

转载自www.cnblogs.com/taltao/p/10093560.html