1、任务编排
1、有一道经典的使用 Channel 进行任务编排的题,你可以尝试做一下:有四个 goroutine,编号为 1、2、3、4。每秒钟会有一个 goroutine 打印出它自己的编号,要求你编写一个程序,让输出的编号总是按照 1、2、3、4、1、2、3、4、……的顺序打印出来。
- 双向通道可以赋值给单向通道,但是单向通道不能赋值给双向通道,不同方向的单向通道也不能互相赋值
- select {} 会阻塞主协程等待子协程
// 解法1
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 4)
for {
for i := 1; i < 5; i++ {
ch <- i
go func() {
st := <-ch
fmt.Println(st)
}()
time.Sleep(1 * time.Second)
}
}
}
// 解法2
package main
import (
"fmt"
"sync"
"time"
)
var (
c1 = make(chan int, 1)
c2 = make(chan int, 1)
c3 = make(chan int, 1)
c4 = make(chan int, 1)
)
func main() {
var wg sync.WaitGroup
wg.Add(4)
c4 <- 1
go func() { //1
for {
time.Sleep(time.Second)
<-c4
fmt.Print(1, " ")
c1 <- 1
}
wg.Done()
}()
go func() { //2
for {
time.Sleep(time.Second)
<-c1
fmt.Print(2, " ")
c2 <- 2
}
wg.Done()
}()
go func() { //3
for {
time.Sleep(time.Second)
<-c2
fmt.Print(3, " ")
c3 <- 3
}
wg.Done()
}()
go func() { //4
for {
time.Sleep(time.Second)
<-c3
fmt.Print(4, " ")
c4 <- 4
}
wg.Done()
}()
wg.Wait()
}
// 解法3
package main
import (
"fmt"
"time"
)
func main() {
chArr := [4]chan struct{}{
make(chan struct{}),
make(chan struct{}),
make(chan struct{}),
make(chan struct{}),
}
for i := 0; i < 4; i++ {
go func(i int) {
for {
<-chArr[i%4]
fmt.Printf("i am %d\n", i)
time.Sleep(1 * time.Second)
chArr[(i+1)%4] <- struct{}{}
}
}(i)
}
chArr[0] <- struct{}{}
select {}
}