本篇面经来自 : https://www.nowcoder.com/feed/main/detail/ac0efc95550947c0a55693799dbfa380?sourceSSR=search
个人背景与项目挖掘
Q : 简单介绍一下目前在职的情况,以及寻找新机会(离职)的原因是什么?
Q : 介绍一下你在做的项目,核心思想和解决的痛点是什么?
两个很普通的问题 : 总结
问题 2 : 预计到时候要准备一篇 500 字的演讲稿方便背诵 。 已添加到 Memo 中 ddl 预计下个月
Go 语言基础
常识题
Q : 项目里用到了 Gin 框架,请问 Gin 第一层的参数绑定(Parameter Binding)底层是怎么实现的?
Gin 支持 Bind 和 ShouldBind 两种调用
|
|
其中通过 Method 来分发对应的实现
|
|
shouldbind 不额外封装 http-code,但是bind额外封装 。
|
|
具体更核心的实现,预计就是读取 http 的请求根据各种字段进行处理。预计只要回答到这一步即可
todo : 整理这部分内容单独到 Gin 中
Q : Go 语言中的 Channel 有什么特点?在使用它的时候需要注意什么?
吐槽一下 : 说实话实际工作中用到 channel 的地方真的很少
目前的印象来说 :
channel 的发送操作和接收操作 会相互阻塞直到双方准备完毕
使用它有什么需要注意的 : 记得 close
todo : 这个后续预计会在系统整理 高并发那一块处理,或者是在补充《协程池》这篇文章后进行针对学习
Q : 如果一个 Channel 已经关闭了,再往里面写数据会发生什么情况?
WrongAnser : 从上面的回答来看,如果接收方的channel关闭,但是发送方的没关闭,预计是会一直阻塞,然后程序运行后会出错 all sleep goroutine, deal lock 印象中是这样
True : panic: send on closed channel
todo : 会一并同上面的问题一起处理
代码输出题
|
|
这个问题是默认补0吧,println不是sprintf(%v)感觉会输出地址? 不过预计答案是 0,0,0,1,2,3
纠正 : fmt.Println 对 slice 用的就是类似 %v 的默认格式,打印的是元素内容:[0 0 0 1 2 3]
Redis
Q : Redis 的分布式锁怎么实现的 ?
不知道,印象中是 setNx 但是没实际实现过
todo : 补在memo中
Q : 如果现在想做一个排行榜功能,应该用 Redis 的哪种数据结构?
Zset, 不过如果要处理 100w 的排行的话 需要在业务上额外处理一下,例如定时排序+Zset 不过这个作业目前还没完成 只是知道一个概念
todo : 补在memo中
Q : Redis 的字符串类型中,有没有哪个指令能够对已存储的数字进行累加?
没看懂这个什么问题,字符串类型的累加? IncrBy() 吗,需要注意的是 如果没有key和有key的情况。这个在 查询和缓存计数的时候有考,预计在下周总结出来
Q : 了解 Redis 的缓存雪崩、缓存穿透和缓存击穿吗?分别是什么以及怎么解决?
吐槽 : 梦会实习面经
缓存雪崩指的是 : 大量数据没有命中缓存 导致都打到数据库上
缓存穿透 : 指的是数据在缓存和数据库中都不存在
缓存击穿 : 热点 key 正好过期,此时又有大量数据引入
解决办法忘记的差不多了,不过从现在的业务理解上面看
- 给数据库进行限流降级,保住一部分用户的使用。 另外使用其他可用的Redis
- 都不存在,那就用 布隆过滤器过滤一下,本质上就是给不存在的key增加一个缓存
- 和方法2差不多,也是缓存一下这个过期的 大V key
Kafka
Q : Kafka 是怎么保证消息消费的有序性的?
没用过 Kafka 不知道
todo : 推进 kakfa 的学习
SQL
|
|
吐槽 : 没想到 26年的面试也是这么存粹,还有手撕sql的环节
这里简单手撕一下,估计牛客上面有原题输入输出什么的预计,这周末去刷一下
|
|
猜测是这样
手撕代码
|
|
这个炫技做法就是 参考我这里的实现吧协程池 ,用协程池开2个goroutine 输出就行了?不过输出的时候全局变量要上锁
感觉不用搞这么麻烦,直接手动开启两个 gouroutine ,然后用 atomic并发安全的基本类也行?
不过怎么实现交替,用管道通信?一个携程输出完 然后传给另外一个 直到 100 然后close ?
写了一下没写出来,看着是 写入方和接收方 不能够同时操作 …
todo: 实现 1-100交替输出
|
|
AI Summary
总评
答对:4 / 11(另有 2 道半对) 评分:48 / 100
按技术题计(不含自我介绍/项目介绍)。能答对的多是「知道用什么」,卡在「怎么做对 / 边界 / 落地」。
逐题核对
| # | 题目 | 判定 | 说明 |
|---|---|---|---|
| 1 | Gin 参数绑定 | ✅ | Bind/ShouldBind、按 Method/ContentType 分发,方向对,面试够用 |
| 2 | Channel 特点与注意 | ⚠️ | 「互相阻塞」只覆盖无缓冲;「记得 close」不准确 |
| 3 | 往已关闭 channel 写 | ❌ | 你自己标了 Wrong;正确是 panic: send on closed channel |
| 4 | make([]int,3) + append |
✅ | [0 0 0 1 2 3] 正确 |
| 5 | Redis 分布式锁 | ❌ | 只想到 setNx,缺过期、value、续期、释放校验 |
| 6 | 排行榜用啥 | ✅ | ZSet 正确 |
| 7 | 字符串累加 | ✅ | INCR/INCRBY 正确 |
| 8 | 雪崩/穿透/击穿 | ⚠️ | 定义大致对,方案混、不完整 |
| 9 | Kafka 有序性 | ❌ | 空白 |
| 10 | SQL 平均年龄 | ❌ | 应用 HAVING,不能 WHERE avg > 20 |
| 11 | 协程交替打印 | ❌ | 没写出;现有代码结构也不对 |
优点
- 会追源码:Gin 那题不是背概念,而是顺着
ShouldBind→Default→MustBindWith,面试里加分。 - 知道错在哪:closed channel、slice 打印都能自纠,学习闭环在。
- 选型直觉还行:排行榜 ZSet、计数 INCR,方向不偏。
- 有复盘习惯:todo / memo 落点清楚,比「看完就过」强。
缺点
- 基础边界不熟:channel close、SQL
HAVING、手撕交替打印 —— 都是高频送分题。 - 中间件偏「听过没用过」:Redis 锁、Kafka 几乎空。
- 缓存三兄弟:定义能背一半,方案和场景对不上(击穿该用互斥/singleflight,不是「再缓存一下」)。
- 手撕偏复杂:交替打印绕 atomic + channel of atomic,反而写挂;面试要最小正确实现。
建议(按优先级)
本周先补这 4 个,能直接拉到 ~65:
-
SQL
SELECT dept_id FROM department GROUP BY dept_id HAVING AVG(age) > 20 -
Channel
无缓冲/有缓冲、close 后读零值、写 panic、nil channel 永久阻塞、谁负责 close
-
交替打印(双 channel 或一个 channel + 两个 goroutine 即可)
|
|
-
Redis 锁一句话版
SET key uuid NX EX 30→ 业务 → Lua 校验 uuid 再 DEL;进阶再提 Redlock / 看门狗续期。
下周: Kafka「单分区有序 + 同 key 进同分区」;缓存三兄弟各配 1 个标准方案(随机 TTL / 布隆或空值 / mutex)。
面试表达: Gin、ZSet 这类题用「结论 → 一句原理 → 一句坑」三段式,比贴大段源码更稳。
一句话: 选型感和复盘习惯不错,但基础题失分多;先把 SQL / Channel / 手撕 / Redis 锁补实,分数会比补 Kafka 涨得更快。