V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
hijoker
V2EX  ›  Go 编程语言

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

  •  
  •   hijoker · 2021-01-11 12:39:09 +08:00 · 4768 次点击
    这是一个创建于 1414 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    • 把 key 放到 slice 里,随机获取 3 个 key

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

    • 对于无缓存的,发送端会短暂的阻塞
    • 对于有缓存的, 看缓存是否已满,如果满了就和无缓存一样

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

    • 不会,gc 不会立即执行

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

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

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

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

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

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

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

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

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

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

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

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

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

    第四个问题,如果请求太多,每个都开一个 goroutine 显的很失控。特别是 goroutine 里对内存有明显压力。你可以 channel request 先。
    Neo10373
        21
    Neo10373  
       2021-01-12 08:42:59 +08:00
    第二题更具体点:
    无缓存,同时发送和接收时,发送端会阻塞,接收端完成接收,发送端解阻塞完成发送;
    有缓冲,发送端阻塞到复制值到缓冲区完成,缓冲区满一直阻塞,接收端阻塞到从缓冲区取值完成,缓冲区空一直阻塞
    BBCCBB
        22
    BBCCBB  
       2021-01-12 08:55:53 +08:00
    3 这个 delete map[key]. map 的容量和 gc 应该没关系?
    hijoker
        23
    hijoker  
    OP
       2021-01-12 23:06:08 +08:00
    @yzbythesea 第三个问题,题目就是每个请求都开一个 goroutine, 是想问你这个服务器会有什么表现,比较开放,这个问题
    drackzy
        24
    drackzy  
       2021-01-14 17:43:16 +08:00
    go 面试也开始内卷了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3621 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 11:04 · PVG 19:04 · LAX 03:04 · JFK 06:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.