1.初始化
声明和初始化管道的方式主要有两种
(1)变量声明
(2)使用内置函数make()
1)变量声明
var ch chan int //声明管道
这种方式声明的管道,值为nil。每个管道只能存储一种类型的数据。
2)使用内置函数make()
使用内置函数make()可以创建无缓冲管道和带缓冲管道
ch1 := make(chan string) //无缓冲管道
ch2 := make(chan string,5) //带缓冲管道
2.管道操作
1)操作符操作符“<-”表示数据流向,管道在左表示向管道写入数据,管道在右表示从管道读出数据,如下所示。
ch := make(chan int,10)
ch <- 1
d := <-ch
fmt.Println(d)
默认的管道为双向可读写,管道在函数间传递的时候可以使用操作符来限制管道的读写。
func ChanParamRW(ch chan int) {//管道可以读写}
func ChanParamRW(ch <-chan int) {//只能从管道读取数据}
func ChanParamRW(ch chan<- int) {//只能从管道读取数据}
管道没有缓冲区时,从管道读取数据会阻塞,直到有协程向管道中写入数据。
向管道写入数据也会阻塞,直到有协程从管道读取数据。
管道有缓冲区但缓冲区没有数据时,从管道读取数据也会阻塞,直到有协程写入数据。
向管道写人数据时,如果缓冲区已满,那么也会阻塞,直到有协程从缓冲区中读出数据。
对于值为nil的管道进行操作,无论是进行读还是写都会阻塞,并且是永久的阻塞。
对于管道的关闭,使用Close()。对关闭的管道进行写入数据会出发panic,而使用Close()进行关闭的管道仍然可以读。
管道的读取操作,同时最多可以给两个变量赋值。
x , ok := <-ch
x表示读出的数据,而ok则表示是否成功的读取了数据,是bool类型的变量。
但是第二个变量ok并不能用于指示管道的关闭状态,常常误解管道的关闭状态和变量ok相关,是因为ok和管道缓冲区中是否有数据相关。
对于一个关闭的管道有两种情况:
1.管道缓冲区已经没有数据了
2.管道缓冲区还有数据
对于第一种情况,管道读取表达式返回的第一个变量为相对应类型的零值,而ok为false。
对于第二种情况,管道读取表达式返回的第一个变量为读取到的数据,第二个变量为true。
也就是说,只有管道的缓冲区没有数据且管道已经关闭的时候,其读取到的ok才和管道的关闭状态是一致的。
3.总结
内置函数len()和cap()分别代表的作用是,查询缓冲区中数据的个数以及缓冲区的大小。
管道的实现是一种先入先出的队列。
协程对管道进行读取的时候阻塞的条件有以下三种:
1.管道没有缓冲区
2.管道的缓冲区是没有数据的
3.管道的值是nil
协程写入管道的时候,阻塞的条件有一下三种:
1.和上面类似,管道没有缓冲区
2.管道的缓冲区是满的
3.管道的值是nil