问题描述
使用两个 goroutine 交替打印序列,一个 goroutinue 打印数字, 另外一个 goroutine 打印字母, 最终效果如下 12AB34CD56EF78GH910IJ。
答案
chan_n := make(chan bool)
chan_c := make(chan bool, 1)
done := make(chan struct{})
go func() {
for i := 1; i < 11; i += 2 {
<-chan_c //这句代码起什么作用?
fmt.Print(i)
fmt.Print(i + 1)
chan_n <- true //这句是往管道里面写数据?有什么用?
}
}()
go func() {
char_seq := []string{"A","B","C","D","E","F","G","H","I","J","K"}
for i := 0; i < 10; i += 2 {
<-chan_n // ?
fmt.Print(char_seq[i])
fmt.Print(char_seq[i+1])
chan_c <- true // ?
}
done <- struct{}{} // ?
}()
chan_c <- true //?
<-done
1
OhYee 2019-10-29 11:46:50 +08:00
<-chan_c 等待管道 chan_c 有数据才继续往下执行
chan_n <- true 往管道 chan_n 写数据 <-chan_n 等待管道 chan_n 有数据才继续往下执行 chan_c <- true 往管道 chan_c 写数据 done <- struct{}{} 往管道 done 写数据 <-done 等待管道 done 有数据才往下执行 总的来说就是两个 goroutine 启动后,都会因为管道为空而阻塞 在 chan_c <- true 这里,向 chan_c 写入数据,从而导致上面的 goroutine 不再阻塞(读到了 chan_c 的数据。 输出 1、2 后,向 chan_n 写入数据,并且在下一个循环中由于 chan_c 没有数据而阻塞 chan_n 读到数据后下面的 goroutine 不再阻塞,开始执行,输出 A、B,并且向 chan_c 写入数据,并且在下一个循环由于 chan_n 没有数据而阻塞 …… 重复上面的过程,直到下面的 goroutine 循环结束,向 done 写入数据 阻塞的主线程在<-done 收到数据,继续执行。后面没代码了,所以结束程序。 |
2
fatbear001 OP @OhYee 按照你所说的:在第二个循环里,chan_c <- true,向 chan_c 写入数据。那既然都向 chan_c 写入数据了,那前面打印字母的代码( fmt.Print(char_seq[i]) fmt.Print(char_seq[i+1]))应该已经执行了吧?不应该先打印字母 AB 吗?我不明白为什么会先打印数字。
|
3
OhYee 2019-10-29 12:10:27 +08:00
1、2 是倒数第二行的 chan_c <- true 触发的
1、2 后面的 chan_n <- true 触发 A、B 然后 A、B 后面的 chan_c <- true 触发 3、4 |
4
lmw2616 2019-10-29 12:25:40 +08:00
先执行的倒数第二行,然后执行打印数字,打印完数字 chan_n 有数据, 才执行打印字母。
你把倒数第二行改为 chan_n <- true,就是先打印字母了 |
5
lmw2616 2019-10-29 12:29:34 +08:00
<-chan,chan 没数据就阻塞,有数据就往下执行
|
6
inhzus 2019-10-29 12:39:02 +08:00 via Android
这个是 go 最基础的语法呀… 去学一下 channel 就好了啊
|
7
jessun1990 2019-10-29 14:00:35 +08:00 via Android
@lmw2616 答案赞同,建议在复习一下 go 中 chan 的使用。强烈推荐 go 高级编程这本书。
|
8
hdbzsgm 2019-10-29 14:12:40 +08:00
都是起 block 作用
|