abstract:channel go语言提供的消息通信机制被称为channel. "不要通过共享内存来通信,而应该通过通信来共享内存". channel是go语言在语言级别提供的goroutine之间的通信方式.是类型相关的,一个channel只能传递一种类型的值.这个类型需要在声明channel的时候指定. 在对应的channel被读取前,这个操作时阻塞的,在所有的goroutine
channel
go语言提供的消息通信机制被称为channel.
"不要通过共享内存来通信,而应该通过通信来共享内存".
channel是go语言在语言级别提供的goroutine之间的通信方式.是类型相关的,一个channel只能传递一种类型的值.这个类型需要在声明channel的时候指定.
在对应的channel被读取前,这个操作时阻塞的,在所有的goroutine启动完成后,我们通过<-ch语句从10个channel中依次读取数据,在对应的channel写入数据前,这个操作也是阻塞的.这样我们就用channel实现了类似锁的功能,进而保证了所有的goroutine完成后主函数才能返回.
go demo package main import ( "fmt" "runtime" ) func Count(ch chan int, i int) { fmt.Println("counting", i) ch <- i fmt.Println("after chan", i) } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) chs := make([]chan int, 10) for i := 0; i < 10; i++ { chs[i] = make(chan int) go Count(chs[i], i) } fmt.Println("start for") for _, ch := range chs { var ii int ii = <-ch fmt.Println("for ", ii) } }
select
go语言直接在语言级别支持select关键字,用于处理异步IO问题.
select 用法与switch类似,最大的一条限制是每个case语句必须是一个IO操作,case后都必须是chan操作
select{ case <-chan1: // 如果成功从chan1成功数据 case chan2<-1: // 如果成功向chan2写入数据 default: //如果都没成功 } // 随机写入 0,1 ch := make(chan int, 1) for a := 0; a < 10; a++ { select { case ch <- 0: case ch <- 1: } i := <-ch fmt.Println(i)
缓冲机制
使用于需要持续传输大量数据的场景, c := make(chan int ,1024),即使没有读取方,写入方也可以一直往channel里写入,在缓冲区填完之前不会被阻塞.
从缓冲区读取数据与常规非缓冲channel完全一致,我们也可以使用range关键字来实现循环读取
超时机制
在往channel写入数据时发现已满,或读取数据时发现为空,如果不正确处理这些数据,很可能导致整个goroutine死锁.
可以结合select 进行超时处理.
channel 包括 双向channel,单项channel(只读channel,只写channel)
关闭channel
close(ch);判断关闭 x,ok := <-ch 只需要判断第二个bool返回值即可.false则表示关闭.