//通过通道发送一个字符串
buffered <- 1
//从通道接收一个字符串
value := <- buffered
无缓冲的Channel
无缓冲的Channel必须有接受者,如果没有接受者(worker)就会报错。
package main
import (
"fmt"
"time"
)
func worker(id int, c chan int) {
for {
fmt.Printf("Worker %d received %d\n",
id, <-c)
}
}
func createWorker(id int) chan<- int {
c := make(chan int)
//Channel的接受者
go worker(id, c)
return c
}
func chanDemo() {
//建立Channel的slice (Channel是一等公民)
var channels [10]chan<- int
//建立10个Channel和接受者
for i := 0; i < 10; i++ {
channels[i] = createWorker(i)
}
//传入值
for i := 0; i < 10; i++ {
channels[i] <- 'a' + i
}
//传入值
for i := 0; i < 10; i++ {
channels[i] <- 'A' + i
}
//程序持续1 Millisecond
time.Sleep(time.Millisecond)
}
func main() {
fmt.Println("Channel as first-class citizen")
chanDemo()
}
package main
import (
"fmt"
"time"
)
func worker(id int, c chan int) {
for {
fmt.Printf("Worker %d received %c\n",
id, <-c)
}
}
func bufferedChannel() {
c := make(chan int, 3)
go worker(0, c)
c <- 'a'
c <- 'b'
c <- 'c'
c <- 'd'
time.Sleep(time.Millisecond)
}
func main() {
fmt.Println("Buffered channel")
bufferedChannel()
}
如果不加worker,程序会报错,但是如果把c <- 'd'也注释掉,程序时不会报错的。
关闭Channel
package main
import (
"fmt"
"time"
)
func worker(id int, c chan int) {
for {
fmt.Printf("Worker %d received %c\n",
id, <-c)
}
}
func channelClose() {
c := make(chan int)
go worker(0, c)
c <- 'a'
c <- 'b'
c <- 'c'
c <- 'd'
close(c)
time.Sleep(time.Millisecond)
}
func main() {
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
func worker2(id int, c chan int) {
for {
n, ok := <-c
if !ok {
break
}
fmt.Printf("Worker %d received %c\n",
id, n)
}
}
写法2
func worker(id int, c chan int) {
for n := range c {
fmt.Printf("Worker %d received %c\n",
id, n)
}
}
package main
import (
"fmt"
)
func doworker(id int, c chan int, done chan bool) {
for n := range c {
fmt.Printf("Worker %d received %c\n",
id, n)
done <- true
}
}
type worker struct {
in chan int
done chan bool
}
func createWorker(id int) worker {
w := worker{
in: make(chan int),
done: make(chan bool),
}
go doworker(id, w.in, w.done)
return w
}
func chanDemo() {
var workers [10]worker
for 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
}
}
func main() {
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
func chanDemo() {
var workers [10]worker
for i := 0; i < 10; i++ {
workers[i] = createWorker(i)
}
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
for _, worker := range workers {
<-worker.done
<-worker.done
}
}
package main
import (
"fmt"
"sync"
)
func doWork(id int,
w worker) {
for n := range w.in {
fmt.Printf("Worker %d received %c\n",
id, n)
w.done()
}
}
type worker struct {
in chan int
done func()
}
func createWorker(
id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: func() {
wg.Done()
},
}
go doWork(id, w)
return w
}
func chanDemo() {
var wg sync.WaitGroup
var workers [10]worker
for i := 0; i < 10; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(20)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func main() {
chanDemo()
}
package main
import (
"fmt"
"math/rand"
"time"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func main() {
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。可以这样写。
package main
import (
"fmt"
"math/rand"
"time"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func worker(id int, c chan int) {
for n := range c {
fmt.Printf("Worker %d received %c\n",
id, n)
}
}
func createWorker(id int) chan<- int {
c := make(chan int)
go worker(id, c)
return c
}
func main() {
w := createWorker(0)
var c1, c2 = generator(), generator()
for {
n := 0
select {
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是否为空。
package main
import (
"fmt"
"math/rand"
"time"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func worker(id int, c chan int) {
for n := range c {
fmt.Printf("Worker %d received %c\n",
id, n)
}
}
func createWorker(id int) chan<- int {
c := make(chan int)
go worker(id, c)
return c
}
func main() {
worker := createWorker(0)
var c1, c2 = generator(), generator()
n := 0
hasValue := false
for {
// nil chan永远不会被select到
var activeworker chan<- int
if hasValue {
activeworker = worker
}
select {
case n = <-c1:
fmt.Println("Received from c1: ", n)
hasValue = true
case n = <-c2:
fmt.Println("Received from c2: ", n)
hasValue = true
case activeworker <- n:
hasValue = false
}
}
}
package main
import (
"fmt"
"math/rand"
"time"
)
func generator() chan int {
out := make(chan int)
go func() {
i := 0
for {
time.Sleep(
time.Duration(rand.Intn(1500)) *
time.Millisecond)
out <- i
i++
}
}()
return out
}
func worker(id int, c chan int) {
for n := range c {
// 让worker故意慢一点
time.Sleep(time.Second)
fmt.Printf("Worker %d received %d\n",
id, n)
}
}
func createWorker(id int) chan<- int {
c := make(chan int)
go worker(id, c)
return c
}
func main() {
var c1, c2 = generator(), generator()
var worker = createWorker(0)
// 建立一个切片来储存数据
var values []int
// time.After在指定时间后往返回Channel你传入时间
tm := time.After(10 * time.Second)
// time.Tick在指定间隔往返回Channel你传入时间
tick := time.Tick(time.Second)
for {
var activeWorker chan<- int
// 定义有效的值
var activeValue int
if len(values) > 0 {
activeWorker = worker
// 永远拿队列第一个值
activeValue = values[0]
}
select {
case n := <-c1:
values = append(values, n)
case n := <-c2:
values = append(values, n)
case activeWorker <- activeValue:
// 将队列第二个值往前移动一位
values = values[1:]
case <-time.After(800 * time.Millisecond):
fmt.Println("timeout")
case <-tick:
fmt.Println(
// 每隔一秒查看队列长度
"queue len =", len(values))
case <-tm:
fmt.Println("bye")
return
}
}
}