Go语言编程读书笔记:Go channel(1)

Channel是Go语言在语言级别提供的goroutine间的通信方式。我们可以用channel在两个或多个goroutine之间传递消息。channel是进程内的通信方式,因此通过channel传递对象的过程和调用函数是的参数传递行为比较一致,比如也可以传递指针等。如果需要跨进程通信,建议用分布式系统的方法来解决,比如用socket或HTTP等通信协议。

channel是类型相关的,也就是说,一个channel只能传递一种类型的值。这个类型需要在声明channel时指定。

一般channel的声明形式为:

var chanName chan ElementType

举个栗子,我们声明一个传递类型为int的channel:

var ch chan int

或者声明一个map,元素是bool的channel:

var m map[string] chan bool

定义一个channel,直接使用make()函数即可:

ch := make(chan int)

在channel的用法中,最常见的包括写入和读出,将一个数据写入channel的语法很直观:

ch <- value

向channel写入数据通常会导致程序阻塞,直到有其他goroutine从这个channel中读取数据,从channel中读取数据的语法是:

value := <- ch

示例:

在这个例子中,我们定义了一个10个channel的数组chs,并把数组中的每个channel分配给10个不同的goroutine,在每个goroutine的print完成后,我们通过ch <- 1向channel中写入一个数据,在这个channel被读取前,这个操作是阻塞的。在所有goroutine启动完成后,我们通过<-ch从10个channel中依次读取数据,在数据写入channel前,这个操作也是阻塞的。这样就实现了锁的功能。

package main

import (
"fmt"
"time"
) func Count(ch chan int) {
fmt.Println("Counting")
time.Sleep(time.Second)
ch <- 1
} func main(){
chs := make([]chan int,10)
for i := 0;i<10;i++ {
chs[i] = make(chan int)
go Count(chs[i])
} for _,ch := range(chs){
<-ch
}
}

 坑:

channel默认上是阻塞的,也就是说,如果Channel满了,就阻塞写,如果Channel空了,就阻塞读。于是,我们就可以使用这种特性来同步我们的发送和接收端。

channel <-,发送一个新的值到通道中 <-channel,从通道中接收一个值,这个更像有两层含义,一个是会返回一个结果,当做赋值来用:msg := <-channel;另外一个含义是等待这个channel发送消息,所以还有一个等的含义在.所以如果你直接写fmt.Print(<-channel)本意只是想输出下这个chan传来的值,但是其实他还会阻塞住等着channel来发.

默认发送和接收操作是阻塞的,直到发送方和接收方都准备完毕。

package main

import "fmt"

func main() {
messages := make(chan string)
go func() {
messages <- "ping"
}()
msg := <-messages
fmt.Println(msg)
} //output:ping

 如果是下面这样写,就会报错,因为msg还在等待message来传送值

func main() {
messages := make(chan string) msg := <-messages messages <- "ping"
fmt.Println(msg)
} //fatal error: all goroutines are asleep - deadlock! //goroutine 1 [chan receive]:

  

 

上一篇:springboot在工具类中添加service的方法,显示为空的解决方案


下一篇:OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)