两个 goroutine 用 channel 通信,一个 goroutine 顺序发送 0,1,2,3,4 个数字,另一个 goroutine 接收并输出。 考察了 goroutine 的控制、channel 的关闭等基础知识,面试者写的代码各种问题。
上周面试 5 个人只有 1 个人一次写出了执行没问题的代码,有 1 个经过提示也没写出来,剩下的能提示后逐步修改出正确的代码。
这个题还是很经典的,不用问 GMP 、垃圾回收算法等八股文,这个题就能看出 go 基础了。
![]() |
1
NerdHND 6 小时 22 分钟前 ![]() 拿我得指出哥们候选人真的有问题吧, 这, 这不是完全不会嘛...
|
2
hingle 6 小时 20 分钟前 ![]() 薪资给多少?薪资低那就 “门当户对” 了,挺好的。
|
![]() |
3
kandaakihito 6 小时 13 分钟前 ![]() 看了一下,上周那个 “一面出 LRU 算法题算难吗” 的帖子也是你发的。老哥你负责面的到底是什么类型岗位呀?怎么题目差距好像有点儿大。
而且说实话,如果给你投简历的人里面,有 80%连 chan 的基础都用不清楚。。。那么你这个岗位面试的时候应该不适合问 LRU 。 |
![]() |
4
nomagick 6 小时 10 分钟前 ![]() 你也别有莫名的优越感然后老来收铜币;
先用务实标准筛选一下吧,统招本科四六级,3 年经验之类的 |
![]() |
5
Keystroke 5 小时 56 分钟前
time.sleep……
|
![]() |
6
clemente 5 小时 56 分钟前
如果说从通过率分布的角度来定义 题的难度的话
90% 应该算 hard |
7
fruitmonster 5 小时 52 分钟前
虽然知道应该使用 waitgroup ,但是, "time sleep " 没解决没执行完就退出这个问题么?
|
![]() |
8
czfy 5 小时 44 分钟前 via Android ![]() 钓鱼上瘾是病,得治
|
![]() |
9
xuanbg 5 小时 42 分钟前
你这个不叫 go 基础,就是个编程基础。
|
10
jworg 5 小时 42 分钟前
可以用第三方库不,我脑子已经被 conc 惯坏了,只记得起 conc 的 WaitGroup , 系统的 WaitGroup 好像属于 sync 包。
|
11
langhuishan 5 小时 41 分钟前
golang 的精髓不就是并发吗?这都没掌握,等于没学
|
![]() |
12
cooooing 5 小时 40 分钟前 via Android
@fruitmonster time sleep 只是降低出现这个问题的概率,并没有解决问题。如果操作是请求 api 或者其他耗时操作,要 sleep 多久?这种方式不好的,还是得 wait group 或者其他方式来同步
|
![]() |
13
Vegetable 5 小时 32 分钟前
这种情况至少说明完全没做过需要 graceful shutdown 的程序,不能说判死刑,但至少对 go 不太了解吧
|
![]() |
14
lasuar 5 小时 14 分钟前
可以说说招聘岗位要求几年经验,给多少薪资
|
![]() |
15
zljklang 4 小时 50 分钟前
package main
import "fmt" func main() { // 创建无缓冲通道 ch := make(chan int) // 发送方 goroutine go func() { for i := 0; i < 5; i++ { ch <- i // 顺序发送数字 } close(ch) // 发送完成后关闭通道[1,7](@ref) }() // 接收方 goroutine for num := range ch { fmt.Println("Received:", num) } } 这个对吗 |
![]() |
16
givenge 4 小时 42 分钟前
天天发这些,不会是想转自媒体吧
|
![]() |
17
opengps 4 小时 36 分钟前
对于你的状态来考他们不合格,那反过来他们提问题考验你你有信心通过吗?
单个问题并不能说明人的整体能力 |
![]() |
18
hunterster 4 小时 30 分钟前
package main
import ( "fmt" "sync" ) func writeData(c chan int, i int) { c <- i } func readData(c chan int) { for i := 0; i < 5; i++ { fmt.Println("The data is:", <-c) } } func main() { var wg sync.WaitGroup wg.Add(5) var c = make(chan int) for k := 1; k <= 5; k++ { go func() { defer wg.Done() writeData(c, k) }() } go readData(c) wg.Wait() close(c) } |
19
codersdp1 4 小时 27 分钟前
这个确实属于 go 基础了,没掌握这些写并发功能肯定会出问题的。
|
![]() |
20
voidmnwzp 4 小时 25 分钟前
```go
func Test2(t *testing.T) { s := make(chan int) go func() { for i := range s { fmt.Println("recv:",i) } }() for i := 0; i < 5; i++ { s <- i } close(s) } ``` 不是这和 1+。。100 求和有啥区别 很难吗 |
![]() |
21
SingeeKing 4 小时 22 分钟前
想当年我也问过这类题,真的大量候选人答不出来😮💨
|
![]() |
22
expy 4 小时 15 分钟前
正常,卷是真的卷,但是水平差的人也大量存在。
|
23
HappyAndSmile 4 小时 13 分钟前
你要求什么工资?我甚至可以答得比你好很多
|
![]() |
25
bv 4 小时 12 分钟前
@SingeeKing 真的假的?都几年经验?这种人招进去也是边学边做吧,甚至还会拖队友后腿。
|
![]() |
26
main1234 4 小时 9 分钟前
package main
import ( "fmt" "sync" ) func main() { sw := sync.WaitGroup{} sw.Add(1) ch := make(chan int) go func() { for i := 0; i < 5; i++ { ch <- i } close(ch) }() go func() { defer sw.Done() for i := range ch { fmt.Println(i) } }() sw.Wait() fmt.Println("done") } |
![]() |
29
yiqiao 3 小时 52 分钟前
@zljklang 你这个方法如果主 goroutine 发送完后立刻退出接收方还在运行导致提前终止吧 ,你可以试着调大循环可以看出来
还是要引入 WaitGroup |
30
Ayanokouji 3 小时 52 分钟前
|
![]() |
31
Licsber 3 小时 32 分钟前
笑死 最近写了个转发助手 和你这个题完全重叠
写出来加双端调试 部署上线测试总共两天吧 来看看我这水平能开多少( ```go // listener 省略 func handleConnection(conn net.Conn) { s := &Session{ Cmd: link_start, Remote: remote, ServerSideRemote: conn.RemoteAddr().String(), ClientID: clientID, } ctx, cancel := context.WithTimeout(context.Background(), connectionTimeout) sessionManager.Set(s.ServerSideRemote, conn) sessionManager.Bind(s.ServerSideRemote, cancel) send, _ := json.Marshal(s) token := mqttClient.Publish(controlTopic, defaultQOS, false, send) if token.Wait() && token.Error() != nil { slog.Error("Publish control packet failed:", "err", token.Error()) sessionManager.Remove(s.ServerSideRemote) return } <-ctx.Done() switch ctx.Err() { case context.Canceled: slog.Info("Link confirmed successfully:", "serversideremote", s.ServerSideRemote) case context.DeadlineExceeded: slog.Warn("Confirmation timeout after 5s:", "serversideremote", s.ServerSideRemote) sessionManager.Remove(s.ServerSideRemote) } } func runServerForwarding(s *Session) { conn, ok := sessionManager.Get(s.ServerSideRemote) if !ok { slog.Error("Connection not found:", "connID", s.ServerSideRemote) return } defer conn.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() topic := topicPrefix + s.ClientSideLocal token := mqttClient.Subscribe(topic, defaultQOS, func(c mqtt.Client, m mqtt.Message) { select { case <-ctx.Done(): return default: slog.Debug("Recv client down:", "recv", m.Payload()) recv, err := hex.DecodeString(string(m.Payload())) if err != nil { slog.Error("HEX decode error:", "err", err) cancel() return } _, err = conn.Write(recv) if err != nil { slog.Warn("TCP write error:", "err", err) cancel() } } }) if token.Wait() && token.Error() != nil { slog.Error("Subscribe client down error:", "err", token.Error()) return } buf := make([]byte, defaultBufSize) for { select { case <-ctx.Done(): return default: conn.SetReadDeadline(time.Now().Add(readTimeout)) n, err := conn.Read(buf) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { slog.Debug("TCP read timeout:", "connID", s.ServerSideRemote) continue } slog.Warn("TCP read error:", "err", err) return } send := hex.EncodeToString(buf[:n]) slog.Debug("Send up:", "send", send) topic := topicPrefix + s.ServerSideRemote token := mqttClient.Publish(topic, defaultQOS, false, send) if token.Wait() && token.Error() != nil { slog.Error("Publish up error:", "err", token.Error()) return } } } } ``` |
![]() |
33
yuanyao OP @hunterster 为啥要五个协程,不增加复杂度吗
|
![]() |
34
MoYi123 3 小时 24 分钟前
我三年前写的困难版本 (多生产者多消费者关 chan) https://github.com/mmooyyii/mmooyyii/blob/master/docs/go/mpmc_channel.md
|
36
jworg 3 小时 11 分钟前
@Ayanokouji 是的,不过基础功能的封装库并不需要经常更新,看了眼作者也还活着。
|
![]() |
37
hanxiansheng 3 小时 6 分钟前 via Android
法拉利跑车连犁田都不会,呵呵
|
39
leehaoze98 2 小时 55 分钟前
面外包或者校招会问两个协程交替打印,一个打印 A~Z ,一个打印 1~100 。
1. 有的人手打从'A'~'Z'的数组 2. 有的人 goroutine 没启动,主进程就退出了 3. 有的人只会处理两个协程打印数量一致的情况,一个打印 26 个,另一个打印 100 个,好多人会死锁。 |
![]() |
41
voidmnwzp 2 小时 47 分钟前
@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() } |
![]() |
42
smallparking 2 小时 44 分钟前
```
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, 所以确实不是一下子写出来的 |
44
ChatGOP 2 小时 36 分钟前
Gobyexample 大把例子。
|
![]() |
45
xiangxiangxiang 2 小时 34 分钟前
写了快两年 go 。。。确实基本没用过 channel ,只有看 b 站学 go 语言的时候用过
WaitGroup 倒是工作中经常用 |
![]() |
46
k9982874 2 小时 27 分钟前
这个不提前复习一下直接上手没 ai 辅助真写不出一次全对
|
![]() |
47
vhwwls 2 小时 19 分钟前
运维路过,这个我觉得应该是贵司的简历筛选出了问题,一楼说的对。
|
![]() |
48
daimazha 2 小时 17 分钟前
我觉得这也是八股文的一种
|
![]() |
50
Nazz 1 小时 54 分钟前
我用 chan 从来不 close
|
51
zhengfan2016 1 小时 38 分钟前 ![]() |
![]() |
52
hunterster 1 小时 35 分钟前
@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) } |
53
Erroad 1 小时 20 分钟前
@zhengfan2016 #50 我建议是他先给他们公司的搞个考试,不合格的都开了再说
|
54
birdhk 1 小时 11 分钟前
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 一下吗 |
55
Co1a 1 小时 2 分钟前
楼主发下邮箱
|
![]() |
56
ForkNMB 1 小时 2 分钟前
刚开始学 go 也以为是八股文看看得了 不上手试试 写的也是简单版本(因为没有具体复杂的场景 写出来当然简单)等真用 go 开发写服务 多个协程下 服务优雅关闭 资源合理释放 生产者消费者怎么稳定的转起来 还是踩了很多坑的= = 面试这个确实能筛人
|
57
sky3hao 53 分钟前
这个还好, 我之前出的面试题是: 用两个 channel 循环打印水分子(H2O), 分子顺序不要求, 但是每一行必须是 2 个 H 加 1 个 O 的组合
|
![]() |
59
body007 37 分钟前
|
60
Jinnrry 35 分钟前 via iPhone ![]() 我面试也问这个题目。感觉和 hr 相关,很多 hr 只看背景,不懂技术,找一堆人过来就 90%都写不出来。
我现在这里 hr 比较专业,基本上一半的人能写出来的。 想来也是搞笑,这些连个协程通信都写不明白的人,讲起垃圾回收,数组扩容,乐观锁悲观锁却能头头是道 |
![]() |
61
guanhui07 30 分钟前
也是八股文的一种 不过如果他能知道 waitGroup 我就让他过
|
![]() |
62
seakee 14 分钟前
```
func main() { num := make(chan int, 5) done := make(chan struct{}) go func() { for n := range num { fmt.Println(n) } close(done) }() go func() { for i := 0; i < 5; i++ { num <- i } close(num) }() <-done } ``` |
![]() |
63
Trim21 2 分钟前
这还八股啊,这不是 go 并发编程的基础知识吗 ...
|