最基础的 go 并发编程题,难倒了 90%的候选人

203 天前
 yuanyao

两个 goroutine 用 channel 通信,一个 goroutine 顺序发送 0,1,2,3,4 个数字,另一个 goroutine 接收并输出。 考察了 goroutine 的控制、channel 的关闭等基础知识,面试者写的代码各种问题。

  1. 有的 goroutine 还没启动程序就退出了,提示后仍想不到使用 waitgroup ,context ,done channel 等手段,而是用 time sleep 等待;
  2. 有的 channel 不知道由生产者关闭,直接在主程序生产者还未发送结束就关闭结果 panic ;
  3. 有的不会检查消费者读关闭 channel 的返回值,程序直接死循环死锁。

上周面试 5 个人只有 1 个人一次写出了执行没问题的代码,有 1 个经过提示也没写出来,剩下的能提示后逐步修改出正确的代码。

这个题还是很经典的,不用问 GMP 、垃圾回收算法等八股文,这个题就能看出 go 基础了。

11957 次点击
所在节点    Go 编程语言
108 条回复
voidmnwzp
203 天前
@phpcyy #40 func Test2(t *testing.T) {
s := make(chan int)
wg:=sync.WaitGroup{}
wg.Add(1)
go func() {
for i := range s {
fmt.Println("go2:",i)
}
fmt.Println("done")
wg.Done()
}()
for i := 0; i < 5; i++ {
s <- i
}
close(s)
wg.Wait()
}
smallparking
203 天前
```
package main

import (
"fmt"
"sync"
)

func send(ch1 chan int) {
for i := range 5 {
ch1 <- i
fmt.Printf("send i: %d\n", i)
}
close(ch1)
}
func recv(wg *sync.WaitGroup, ch1 chan int) {

// wait receive all data and done
for i := range ch1 {
fmt.Printf("receive i: %d\n", i)
}
wg.Done()

}
func main() {
var wg sync.WaitGroup
ch1 := make(chan int)
wg.Add(1)
go send(ch1)
go recv(&wg, ch1)
wg.Wait()
}
```

确实有点难度,一般不会启两个 goroutine, 所以确实不是一下子写出来的
phpcyy
203 天前
@voidmnwzp 这个没问题。楼上有例子,你把生产者放 goroutine 先,然后消费者放到 main 函数里,,是最简单的实现
ChatGOP
203 天前
Gobyexample 大把例子。
xiangxiangxiang
203 天前
写了快两年 go 。。。确实基本没用过 channel ,只有看 b 站学 go 语言的时候用过

WaitGroup 倒是工作中经常用
k9982874
203 天前
这个不提前复习一下直接上手没 ai 辅助真写不出一次全对
vhwwls
203 天前
运维路过,这个我觉得应该是贵司的简历筛选出了问题,一楼说的对。
daimazha
203 天前
我觉得这也是八股文的一种
ChatGOP
203 天前
@daimazha 是的, 八股文。 而且哥觉得凡是八股文,AI/Google 能做的都不算是真正的能力
Nazz
203 天前
我用 chan 从来不 close
zhengfan2016
203 天前
只能说 op 招聘错方向了,你招的 985 ,211 都是市场里不缺面试机会的那一批。如果不是特别热爱代码的,也不会去钻研这些东西,反正 curd 就能轻松把钱拿,下班了打游戏不香吗。

倒是那些学历低人一等的大专和普本,有少部分人为了在竞争中脱颖而出,可能真会去钻研这种东西,而聪明的 op 已经把这种可能性过滤掉了。

至此,面试者百分之 90%不会不是很正常吗
hunterster
203 天前
@yuanyao 这个是看到要求随手写的,没注意到只要两个协程,我改一下

package main

import (
"fmt"
"sync"
)

var wg sync.WaitGroup

func init() {
wg.Add(5)
}

func writeData(c chan int, count int) {
fmt.Println("Write rountine is executed.")
for k := 0; k < count; k++ {
defer wg.Done()
c <- k
}
}

func readData(c chan int, count int) {
fmt.Println("Read rountine is executed.")
for i := 0; i < count; i++ {
fmt.Println("The data is:", <-c)
}
}

func main() {

var c = make(chan int)

go writeData(c, 5)
go readData(c, 5)

wg.Wait()
close(c)
}
Erroad
203 天前
@zhengfan2016 #50 我建议是他先给他们公司的搞个考试,不合格的都开了再说
birdhk
203 天前
package main

import "sync"

func main() {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 10000; i++ {
ch <- i
}
close(ch)

}()
go func() {
defer wg.Done()
for i := range ch {
println(i)
}
}()
wg.Wait()
}
我感觉我这样应该没问题,有大哥们 review 一下吗
Co1a
203 天前
楼主发下邮箱
ForkNMB
203 天前
刚开始学 go 也以为是八股文看看得了 不上手试试 写的也是简单版本(因为没有具体复杂的场景 写出来当然简单)等真用 go 开发写服务 多个协程下 服务优雅关闭 资源合理释放 生产者消费者怎么稳定的转起来 还是踩了很多坑的= = 面试这个确实能筛人
PUR4uF5Oq0z0YN9r
203 天前
这个还好, 我之前出的面试题是: 用两个 channel 循环打印水分子(H2O), 分子顺序不要求, 但是每一行必须是 2 个 H 加 1 个 O 的组合
ChatGOP
203 天前
@ForkNMB 其实招人的, 如果自己没有看过这题没有准备, 拿这题考他自己, 也会被筛出局。
body007
203 天前
@hunterster #52 看到循环里面用 defer ,jb 都报警告了。生产环境被同事这种代码坑过
Jinnrry
203 天前
我面试也问这个题目。感觉和 hr 相关,很多 hr 只看背景,不懂技术,找一堆人过来就 90%都写不出来。

我现在这里 hr 比较专业,基本上一半的人能写出来的。

想来也是搞笑,这些连个协程通信都写不明白的人,讲起垃圾回收,数组扩容,乐观锁悲观锁却能头头是道

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

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

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

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

© 2021 V2EX