packagemainimport"fmt"funcmain() { ic :=make(chanint, 3) ic <-100 ic <-200close(ic) // 关闭管道// 再次写入就会报错// ic <- 300 // panic: send on closed channel// 但是可以继续读取 n :=<-ic fmt.Println(n)}
注意,当从一个被关闭的通道中拿取数据时,如果通道中没有数据,该操作将不会再阻塞,而是返回一个false的状态位:n, ok := <- ic,ok == false
遍历channel
packagemainimport"fmt"funcmain() { ic :=make(chanint, 3) ic <-100 ic <-200 ic <-300// panic: send on closed channel// 如果放入之后,没有关闭,在循环取出时,取出到最后一条,将会发生死锁错误close(ic)for i :=range ic { fmt.Printf("i=%v\n", i) // 假设没有关闭,将会报错 error: all goroutines are asleep - deadlock! }}
上面的代码等同于如下循环:
packagemainimport"fmt"funcmain() { ic :=make(chanint, 3) ic <-100 ic <-200 ic <-300// panic: send on closed channel// 如果放入之后,没有关闭,在循环取出时,取出到最后一条,将会发生死锁错误close(ic)for { i, ok :=<-icif!ok {break } fmt.Printf("i=%v\n", i) // 假设没有关闭,将会报错 error: all goroutines are asleep - deadlock! }}
只写只读管道
packagemainfuncmain() {// 默认情况下,管道是双向的,也就是可读可写var chan1 chanint// 也可以在声明管道时,将管道设置为只读或者只写// 只写管道var chan2 chan<-int chan2 =make(chanint, 3) chan2 <-20 num :=<- chan2 // Invalid operation: <- chan2 (receive from the send-only type chan<- int)// 只读管道var chan3 <-chanint chan3 =make(chanint, 3) chan3 <-30// Invalid operation: chan3 <- 30 (send to the receive-only type <-chan int)}
**使用场景:**可以限制某个协程只读、只写管道,如下:
packagemainimport ("fmt""sync")var wg sync.WaitGroupfuncmain() { c :=make(chanint, 3) wg.Add(2)go send(c)go recv(c) wg.Wait()}// 发送方只写funcsend(c chan<-int) {for i :=0; i <10; i++ { c <- i }close(c) wg.Done()}// 接收方只读funcrecv(c <-chanint) {for i :=range c { fmt.Println(i) } wg.Done()}