Go 中的 channel 是 goroutine 之间的通信机制。
Go 实现并发的方式是:“不是通过共享内存通信,而是通过通信共享内存。” 当你需要将值从一个 goroutine 发送到另一个 goroutine 时,将使用 channel。

创建channel

创建 channel,需使用内置的 make() 函数,如下所示:

c1 := make(chan string) //无缓存channel
c2 := make(chan int, 1) //有缓冲
无缓冲: 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-c1 接手了这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着。
有缓冲: c2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

一个 channel 可以执行两项操作:发送数据和接收数据。

ch <- x // sends (or write) x through channel ch
x = <-ch // x receives (or reads) data sent to the channel ch
<-ch // receives data, but the result is discarded

关闭channel

可在 channel 中执行的另一项操作是关闭 channel。
若要关闭 channel,需使用内置的 close() 函数,如下所示:

close(ch)
//若是定义了通道的变量,但是没有通过make函数进行初始化
//使用了close函数,就会报错:panic: close of nil channel

for循环读取channel

for i := range ch { // ch关闭时,for循环会自动结束
    fmt.println(i)
}

防止读取超时channel

select {
    case <- time.After(time.Second*2):
        fmt.println("read channel timeout")
    case i := <- ch:
        fmt.println(i)
}

防止写入超时channel

select {
    case <- time.After(time.Second *2):
        println("write channel timeout")
    case ch <- "hello":
        println("write ok")
}

channel 的 size 最好是 1 或者是 unbuffered

在使⽤用 channel 的时候,最好将 size 设置为 1 或者使⽤用 unbuffered channel。
其他 size 的 channel往往都会引⼊入更更多的复杂度,需要更更多考虑上下游的设计。

举例说明:

1.初始化

	ExpireSignal = make(chan int, 1)

2.更新channel

//在需要处调用
func (p *StreamPool) updateExpireSignal(signal int) {
	ExpireSignal <- signal //ExpireSignal中写入signal
}

3.读取channel,进行处理

//常驻监听ExpireSignal信号
func DealExpireSignal() {
	go func() {
		for {
			select {
			case ch := <-ExpireSignal: //监听超时信号
				//0-默认值
				//1-命令行
				if ch == 1 {
					//根据超时信号处理
					fmt.Println("ExpireSignal:", ch)
					ExpireSignal <- 0
				}
			}
		}
	}()
}