读阻塞阻塞
  1. 写和读一般放在2个go程,否则容易死锁
  2. 如果阻塞发生在主go程,并且没有其他goroutine在运行,会导致程序挂掉
  3. 当管道中的数据读完后,再继续读,存在以下两种情况
  • 通道已经close,则读出的是通道内类型的零值
  • 通道未close,会发生阻塞

管道的遍历的两种方式如下:

func recvChan(ch <-chan int) {for val := range ch {fmt.Println(val)}
}
func main() {var ch chan intch = make(chan int, 2)ch <- 0ch <- 4close(ch)go recvChan(ch)time.Sleep(time.Second * 6)
}

或者

func recvChan(ch <-chan int) {for {val,ok := <-chif !ok {break}fmt.Println(val)}
}
func main() {var ch chan intch = make(chan int, 2)ch <- 0ch <- 4close(ch)go recvChan(ch)time.Sleep(time.Second * 6)
}

无缓冲通道

无缓冲通道,即通道的容量为0,如果在主go程中写,必须先开启读go程,才能不挂掉;
如果在非主go程中写,则会阻塞,程序不会崩

<- 和 ->的所有作用

var ch chan int var ch <-chan intvar ch chan<- intch <- 3<-chval := <-ch

应用示例:
监控标准输入的值,将其写入管道,然后将管道返回,供用户调用。

package mainimport "fmt"type ChanMsg struct {c chan string
}func NewChanMsg() *ChanMsg {return &ChanMsg{c: make(chan string)}
}
func (cs *ChanMsg) Consume() <-chan string{go func() {for {var i string_, _ = fmt.Scanln(&i)cs.Gen(i)}}()return cs.c
}
func (cs *ChanMsg) Gen(i string) {cs.c <- i
}func main() {cs := NewChanMsg()c :=  cs.Consume()for val := range c {fmt.Println(val)}
}

chan优雅的关闭

https://qcrao91.gitbook.io/go/channel/ru-he-you-ya-di-guan-bi-channel