packagemainimport ("fmt""time")funcworker(id int, c chanint) {for { fmt.Printf("Worker %d received %c\n", id, <-c) }}funcbufferedChannel() { c :=make(chanint, 3)goworker(0, c) c <-'a' c <-'b' c <-'c' c <-'d' time.Sleep(time.Millisecond)}funcmain() { fmt.Println("Buffered channel")bufferedChannel()}
如果不加worker,程序会报错,但是如果把c <- 'd'也注释掉,程序时不会报错的。
关闭Channel
packagemainimport ("fmt""time")funcworker(id int, c chanint) {for { fmt.Printf("Worker %d received %c\n", id, <-c) }}funcchannelClose() { c :=make(chanint)goworker(0, c) c <-'a' c <-'b' c <-'c' c <-'d'close(c) time.Sleep(time.Millisecond)}funcmain() { fmt.Println("Channel close and range")channelClose()}
Channel close and range
Worker 0 received a
Worker 0 received b
Worker 0 received c
Worker 0 received d
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
Worker 0 received
如何对应这个问题可以有2种写法。
写法1
funcworker2(id int, c chanint) {for { n, ok :=<-cif!ok {break } fmt.Printf("Worker %d received %c\n", id, n) }}
写法2
funcworker(id int, c chanint) {for n :=range c { fmt.Printf("Worker %d received %c\n", id, n) }}
packagemainimport ("fmt")funcdoworker(id int, c chanint, done chanbool) {for n :=range c { fmt.Printf("Worker %d received %c\n", id, n) done <-true }}typeworkerstruct { in chanint done chanbool}funccreateWorker(id int) worker { w :=worker{ in: make(chanint), done: make(chanbool), }godoworker(id, w.in, w.done)return w}funcchanDemo() {var workers [10]workerfor i :=0; i <10; i++ { workers[i] =createWorker(i) }for i :=0; i <10; i++ { workers[i].in <-'a'+ i<-workers[i].done }for i :=0; i <10; i++ { workers[i].in <-'A'+ i<-workers[i].done }}funcmain() { fmt.Println("Channel as first-class citizen")chanDemo()}
这个程序跑出来的结果如下:
orker 0 received a
Worker 1 received b
Worker 2 received c
Worker 3 received d
Worker 4 received e
Worker 5 received f
Worker 6 received g
Worker 7 received h
Worker 8 received i
Worker 9 received j
Worker 0 received A
Worker 1 received B
Worker 2 received C
Worker 3 received D
Worker 4 received E
Worker 5 received F
Worker 6 received G
Worker 7 received H
Worker 8 received I
Worker 9 received J
packagemainimport ("fmt""math/rand""time")funcgenerator() chanint { out :=make(chanint)gofunc() { i :=0for { time.Sleep( time.Duration(rand.Intn(1500)) * time.Millisecond) out <- i i++ } }()return out}funcmain() {var c1, c2 =generator(), generator()for {select {case n :=<-c1: fmt.Println("Received from c1: ", n)case n :=<-c2: fmt.Println("Received from c1: ", n) } }}
执行结果:
Received from c1: 0
Received from c2: 0
Received from c2: 1
Received from c1: 1
Received from c1: 2
Received from c2: 2
Received from c1: 3
^Csignal: interrupt
假如我想把c1和c2的值传给之前写的worker。可以这样写。
packagemainimport ("fmt""math/rand""time")funcgenerator() chanint { out :=make(chanint)gofunc() { i :=0for { time.Sleep( time.Duration(rand.Intn(1500)) * time.Millisecond) out <- i i++ } }()return out}funcworker(id int, c chanint) {for n :=range c { fmt.Printf("Worker %d received %c\n", id, n) }}funccreateWorker(id int) chan<-int { c :=make(chanint)goworker(id, c)return c}funcmain() { w :=createWorker(0)var c1, c2 =generator(), generator()for { n :=0select {case n =<-c1: fmt.Println("Received from c1: ", n)case n =<-c2: fmt.Println("Received from c2: ", n)case w <- n: } }}
但是这样写有个问题,由于generator需要等待,所以在一开始的时候,会走很多遍case w <- n同时输出0。所以我们在传给worker之前,需要检查n是否为空。
packagemainimport ("fmt""math/rand""time")funcgenerator() chanint { out :=make(chanint)gofunc() { i :=0for { time.Sleep( time.Duration(rand.Intn(1500)) * time.Millisecond) out <- i i++ } }()return out}funcworker(id int, c chanint) {for n :=range c { fmt.Printf("Worker %d received %c\n", id, n) }}funccreateWorker(id int) chan<-int { c :=make(chanint)goworker(id, c)return c}funcmain() { worker :=createWorker(0)var c1, c2 =generator(), generator() n :=0 hasValue :=falsefor {// nil chan永远不会被select到var activeworker chan<-intif hasValue { activeworker = worker }select {case n =<-c1: fmt.Println("Received from c1: ", n) hasValue =truecase n =<-c2: fmt.Println("Received from c2: ", n) hasValue =truecase activeworker <- n: hasValue =false } }}