golang的chan翻译成中文就是管道,顾名思义,就是管道的一端用来读,另一端用来写,这与write和read函数的性质是非常相似的,比如说管道中没数据,就会发生读阻塞,管道中数据是满的,就会发生写阻塞。又类似生产者和消费者,也就是必须有生产(写),才能消费(读)
chan是用来进行go程间通信的,chan的相关操作有发送、接收、关闭,管道是一种引用类型
len函数可以获取通道内元素的数量,cap函数获取通道的容量
注意:1. 使用chan前必须make
2. 对chan的写和读操作必须同时存在,否则会死锁
3. 写和读一般放在2个go程,否则容易死锁
4. 必须要在数据超出通道capicity前,开启读通道,否则会死锁
5. 如果阻塞发生在主go程,会导致程序挂掉
6. 当管道中的数据读完后,再继续读,存在以下两种情况
- 通道已经close,则读出的是通道内类型的零值
- 通道未close,会发生阻塞
管道遍历注意事项:当写完数据后最好进行close,否则遍历读的时候会发生永久阻塞
func recvChan(ch <-chan int) {
for val := range ch {
fmt.Println(val)
}
}
func main() {
var ch chan int
ch = make(chan int, 2)
ch <- 0
ch <- 4
close(ch)
go recvChan(ch)
time.Sleep(time.Second * 6)
}
或者
func recvChan(ch <-chan int) {
for {
val,ok := <-ch
if !ok {
break
}
fmt.Println(val)
}
}
func main() {
var ch chan int
ch = make(chan int, 2)
ch <- 0
ch <- 4
close(ch)
go recvChan(ch)
time.Sleep(time.Second * 6)
}
无缓冲通道
无缓冲通道,即通道的容量为0,如果在主go程中写,必须先开启读go程,才能不挂掉;
如果在非主go程中写,则会阻塞,程序不会崩
- 表示类型,var ch chan int普通通道,var ch <-chan int 只读通道,var ch chan<- int只写通道
- 表示运算符,ch <- 3,向ch通道发送数据(写),<-ch或val := <-ch从ch通道中接收数据(读)
应用示例:
监控标准输入的值,将其写入管道,然后将管道返回,供用户调用。
这里只是抛砖引玉,实际上,可以监控socket连接,把收入的数据全部写入管道,用户操作管道即可
package main
import "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)
}
}



