c := make(chanint) done := make(chanbool) n := 10 // 生产者:大黄 gofunc() { for i := 0; i < 100; i++ { fmt.Println("生成者生产数据:", i) c <- i } close(c) }()
for i := 0; i < n; i++ { // 消费者:小明 gofunc(idx int) { // range 会一直不断检测c管道中的数据,如果有,读取,否则等待,直到显示的close关闭通道 for n := range c { fmt.Println("消费者",idx,"消费数据:", n) } done <- true }(i) }
func main() { // c是一个管道 c := incrementor() //把管道作为返回值 cSum := puller(c) //把管道作为参数 for n := range cSum { fmt.Println(n) // 0 ...9 } }
// 类型:func () chan int // chan int 返回值类型 func incrementor() chan int { // 创建一个管道 out := make(chan int) // 通过主线程创建一个分线程 go func() { //子线程 for i := 0; i < 10; i++ { out <- i //生产数据 } close(out) }() // 返回out管道 return out }
// 函数类型:func (chan int) chan int // 返回值类型:chan int // 参数类型:chan int func puller(c chan int) chan int { // 创建一个新的管道 out := make(chan int) // 创建一个子线程 go func() { var sum int
// <-c // 通过range取读取管道c里面的数据,这个for跳出循环的时间为管道c被关闭 for n := range c { sum += n }
// out <- sum 什么时候执行? out <- sum //生产者 close(out) }() return out }
3、单向管道、双向管道
双向通道: 前面我们以var c chan int形式声明的通道,即类型为chan type的channel都是双向通道。双向通道顾名思义,就是能存数据又能读数据 单向通道: 单向通道,就是只能存或只能读的channel 声明单向通道:
1 2 3 4 5
var readChan <-chan int // 只读的channel var c WriteChan<- int // 只写的channel