一道 Go 的面试题,答案看不懂,有大佬解释下吗?

2019-10-29 11:16:01 +08:00
 fatbear001

问题描述
使用两个 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
2061 次点击
所在节点    问与答
8 条回复
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 收到数据,继续执行。后面没代码了,所以结束程序。
fatbear001
2019-10-29 11:58:39 +08:00
@OhYee 按照你所说的:在第二个循环里,chan_c <- true,向 chan_c 写入数据。那既然都向 chan_c 写入数据了,那前面打印字母的代码( fmt.Print(char_seq[i]) fmt.Print(char_seq[i+1]))应该已经执行了吧?不应该先打印字母 AB 吗?我不明白为什么会先打印数字。
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
lmw2616
2019-10-29 12:25:40 +08:00
先执行的倒数第二行,然后执行打印数字,打印完数字 chan_n 有数据, 才执行打印字母。

你把倒数第二行改为 chan_n <- true,就是先打印字母了
lmw2616
2019-10-29 12:29:34 +08:00
<-chan,chan 没数据就阻塞,有数据就往下执行
inhzus
2019-10-29 12:39:02 +08:00
这个是 go 最基础的语法呀… 去学一下 channel 就好了啊
jessun1990
2019-10-29 14:00:35 +08:00
@lmw2616 答案赞同,建议在复习一下 go 中 chan 的使用。强烈推荐 go 高级编程这本书。
hdbzsgm
2019-10-29 14:12:40 +08:00
都是起 block 作用

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/613966

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX