第一次面试遇到的问题。
问题介绍
n 个 goroutine 顺序输出 1-100
eg:
2 个 goroutine:
goroutine 0 : 1
goroutine 1 : 2
goroutine 0 : 3
我的不优雅做法
虽然结果是正确的,但实际不是面试官想要的方式。只要 sleep 稍微少一点,就会因为调度的问题导致结果不正确。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package main
import (
"fmt"
"time"
)
func run(i int, c chan int) {
for {
n, is := <- c
if is {
fmt.Printf("goroutine %d : %d\n", i, n)
}
}
}
func main() {
n := 0
fmt.Scan(&n)
s := make([]chan int, n)
for i := 0; i < n; i++ {
s[i] = make(chan int, 1)
go run(i, s[i])
}
for i := 0; i < 100; i++ {
s[i%n] <- i+1
time.Sleep(time.Microsecond*800)
}
}
|
面后反思:正确优雅做法
上面用 chan 来控制顺序,但可以直接用 chan 作为 n 个 goroutine 通信,完成了就通知下一个,即下一个 chan 是依赖上一个 chan 完成后来发送消息通知的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package main
import (
"fmt"
"time"
)
var n int
func run(i int, c []chan int) {
for {
var count int
count, ok := <- c[i]
if !ok {
break
}
fmt.Printf("goroutine %d : %d\n", i, count)
if count == 100 {
for i := range c {
close(c[i])
}
break
}
// 通知下一个 G
c[(i+1)%n] <- count+1
}
}
func main() {
fmt.Scan(&n)
s := make([]chan int, n)
for i := 0; i < n; i++ {
s[i] = make(chan int, 1)
go run(i, s)
}
s[0] <- 1
time.Sleep(time.Second)
}
|
End