各位老铁,这几个面试问题怎么回答(回答的圆满不)?

2021-01-11 12:39:09 +08:00
 hijoker

如果从一个 map 里随机抽取 3 个 key,概率保持一样,要怎么做

channel,2 个 goroutine 同时发送和接收,会发生什么?

map 里的元素被 delete 后,map 的内存的体积会不会立即减小

一个 work server,每次收到一个请求,就创建一个协程去处理这个请求,里面有大量的 slice,append 这种情况,短时间请求特别多,这个服务器会发生什么情况

4778 次点击
所在节点    Go 编程语言
24 条回复
virusdefender
2021-01-11 13:04:47 +08:00
map 就是随机的,直接 for 循环取前三个就行吧
hijoker
2021-01-11 13:07:44 +08:00
@virusdefender 在数量不大的情况下,好像并不是很随机
CEBBCAT
2021-01-11 13:11:47 +08:00
我觉得想问的还是 runtime 实现,但好像回答没有怎么涉及。特别是那个 map 删除键值的,确实不会立即减小,但原因不是 gc 而是 map 的内存结构
CEBBCAT
2021-01-11 13:12:10 +08:00
不过感谢分享面试题
Aoang
2021-01-11 13:13:09 +08:00
第二个问题,对于 channel 两个协程进行收发,你的短暂的阻塞的说法是错误的。

一个协程给 channel 发消息,一个协程从 channel 接收,要求是这两个协程都准备好,才能完成收发操作。

形象一点的例子就是,快递员给你送快递,你要去拿快递,通过沟通约定了时间地点,快递员得带着快递过去,你得过去拿,这样才能完成这个流程。

而对于有缓冲的 channel,是不需要收发同步的,但是队列满了之后就和无缓冲的一样了。

所以,同时收发会直接完成这一次消息传递。非同时收发,那么发送端会被阻塞,接收端也会被阻塞。
carlclone
2021-01-11 13:14:41 +08:00
体积那题不是考察 gc , 哈希表有装填因子,大于或小于的时候才会执行 resize
hijoker
2021-01-11 13:31:15 +08:00
@carlclone 感谢
hijoker
2021-01-11 13:31:37 +08:00
@Aoang 感谢
Aoang
2021-01-11 13:32:43 +08:00
关于 map 中的 key 被删除之后 gc 的问题,不是特别好回答。印象中这个问题很早就有人在 github 提出 issues 过,刚刚找出来了。

https://github.com/golang/go/issues/20135

可以去看看进展
baiyi
2021-01-11 13:35:35 +08:00
1.没理解
2.channel 内部有锁实现线程安全,剩下的就是 goroutine 阻塞唤醒等流程
3.不会,map 没有缩容机制,内存占用只会越扩越多
4.大量的 slice append 操作会导致大量的 内存拷贝,应该是考的这个吧

以上是根据 1.13 版本源码的理解,现在可能不准确
hijoker
2021-01-11 13:51:22 +08:00
@Aoang 我也刚刚看到这个了
guonaihong
2021-01-11 17:27:13 +08:00
如果是我回答的话。1,4
把 map 的值 copy 到 slice 。然后使用 Fisher-Yates 算法保持概率一样。

第 4 个需要问 slice 的大小。机器的 total memory 。是否使用 sync.Pool 。综合考虑多个变量。最后看增加和消费的速度,可能有两种情况。可能爆生成者 > 消费者(内存回收),可能生成者==消费者平衡(内存回收),就是不加不减。(如果不引入速度的话,这题描述的有 bug)。(还有一种概率小的情况生成者 < 消费者(内少回收) 基本不可能发生)。
bruce0
2021-01-11 20:21:10 +08:00
@carlclone 我记得 go 的 map 内存占用不会随着元素的 Delete 而出发 resize 的,例如 原来 map 中有 100 个元素,这时 map 占用内存 10M 现在把 map 的元素删除 90 个, map 还是占用 10M 内存, 当然,元素会被 gc 回收掉.

我没有研究过源码, 只是看别人的分析文章了解的,不正确还请指正
carlclone
2021-01-11 22:43:47 +08:00
@bruce0 go 的好像确实是不会,我的有问题,我是按照一般的 map 回答的
momo733
2021-01-11 22:52:06 +08:00
最后的那个应该是 cpu 会暴涨吧,说到 append,应该是要问 append 扩容
momo733
2021-01-11 22:55:05 +08:00
@momo733 当然内存也涨的。。
carlclone
2021-01-11 23:00:45 +08:00
@bruce0 查了一下 java 的 hashmap 也不缩容....目前就只在哈希表学习时和 redis 哈希表里见到过缩容操作,可能是缩容的性价比确实不高吧
liuhan907
2021-01-12 01:21:59 +08:00
@hijoker
第一题我觉得是考察随机采样算法,最常见的蓄水池算法就可以处理。
lihongming
2021-01-12 01:45:38 +08:00
@carlclone 虽然不懂 go,但现代系统确实不再流行缩容,因为现在最贵的硬件资源是 CPU 。

这个概念在学 nosql 的时候被反复提及,以前流行关系数据库是因为它可以节约存储空间(以前最贵的硬件资源),代价就是数据用的时候需要临时组装,耗费 CPU 资源。但现在 CPU 成了最贵的硬件资源,所以就把数据按读取时需要的格式存储,冗余也没问题,只要能尽量减少临时组装数据。

所以,除非过大的哈希表影响了整体速度,否则不缩
yzbythesea
2021-01-12 03:30:08 +08:00
我觉得前三个回答得都可以。

第四个问题,如果请求太多,每个都开一个 goroutine 显的很失控。特别是 goroutine 里对内存有明显压力。你可以 channel request 先。

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

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

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

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

© 2021 V2EX