Golang面试题库(Context、Channel)

Golang 面试题库:Context + Channel 高频核心(2026 大厂真实风格整理)

Context 和 Channel 是 Go 并发编程的两大基石,几乎所有中高级 Go 岗位面试都会深挖这两块(字节、阿里、腾讯、快手、美团等大厂最爱)。
下面按难度分层整理 最常考的 30+ 题,附答案要点 + 代码示例 + 追问方向,建议先自己答一遍再对答案。

一、Channel 基础 & 中级(80% 面试必考)

  1. channel 是什么?它解决了什么问题?
    答:channel 是 goroutine 之间安全通信的管道(类型安全、同步原语)。
    解决:共享内存 → 通信(Don’t communicate by sharing memory; share memory by communicating)。
  2. 有缓冲 channel 和无缓冲 channel 的区别?(最经典) 维度 无缓冲(make(chan T)) 有缓冲(make(chan T, n)) 发送行为 必须有接收方同时就绪才不阻塞 缓冲未满不阻塞 接收行为 必须有发送方同时就绪才不阻塞 缓冲有数据不阻塞 同步性 强同步(发送=握手) 异步(生产消费解耦) 典型场景 严格顺序、同步点 生产者-消费者、限流、任务队列 死锁风险 高(没人收就永久阻塞) 低(但缓冲满也会阻塞)
  3. 下面代码会死锁吗?为什么?(手写题常考)
   func main() {
       ch := make(chan int)  // 无缓冲
       ch <- 1
       fmt.Println(<-ch)
   }

答:死锁。main goroutine 先发送,无人接收 → 永久阻塞。

  1. 如何优雅关闭 channel?几种方式对比 方式 代码示例 适用场景 缺点/注意 close(ch) close(ch) 发送方唯一、明确结束 关闭后仍可读(得零值+ok=false) for range for v := range ch {} 接收方不知道何时结束 — 带 done 信号 channel done := make(chan struct{}) 多发送方、广播关闭 额外 channel 开销 context 取消 ctx, cancel := context.WithCancel() 带超时/取消的场景 最推荐(现代写法)
  2. select 语句的作用?default 和 nil channel 的行为?
   select {
   case v := <-ch1:
       // ...
   case ch2 <- x:
       // ...
   default:
       // 非阻塞执行
   }
  • 多个 case 同时就绪 → 随机选择一个执行(公平性)
  • 所有 case 都不就绪 → 执行 default(若无 default 则阻塞)
  • nil channel 的 case → 永远不就绪(常用于动态禁用分支)
  1. range channel 时如何判断 channel 已关闭?
   for v := range ch { ... }               // 自动退出(推荐)
   // 或
   for {
       v, ok := <-ch
       if !ok { break }                    // ok=false 表示关闭
   }

二、Context 高频题(大厂最爱追问)

  1. context 的四大作用?(背下来)
  2. 传递取消信号(Cancel)
  3. 传递截止时间 / 超时(Deadline / Timeout)
  4. 传递请求域值(WithValue,键值对,慎用)
  5. 链式派生(父 ctx 取消 → 子 ctx 自动传播)
  6. context.Background() 和 context.TODO() 区别?
  • Background():根上下文,永不取消、无值、无截止时间(起点)
  • TODO():当你不知道用什么上下文时占位(提醒后续替换,语义上“待办”)
  1. 如何用 context 控制 goroutine 退出?(最常手写)
   ctx, cancel := context.WithCancel(context.Background())
   defer cancel()  // 防止泄漏

   go func() {
       for {
           select {
           case <-ctx.Done():
               fmt.Println("退出:", ctx.Err())
               return
           default:
               // 业务逻辑
           }
       }
   }()

   // 某处调用 cancel() 触发退出
  1. context.WithTimeout / WithDeadline / WithCancel / WithValue 区别与适用场景 函数 特点 典型场景 WithCancel 手动 cancel() 触发 需要显式停止的 worker/long poll WithTimeout 自动超时后取消 HTTP 请求、数据库查询超时 WithDeadline 指定绝对时间点截止 定时任务、预约截止 WithValue 携带键值对 传 traceID、userID(慎用!)
  2. context 误用有哪些?(大厂最爱问)
    • 全局变量存 context(违背请求域原则)
    • 把 context 存结构体字段(容易泄漏)
    • 忽略 cancel() 调用 → goroutine 泄漏
    • WithValue 滥用 → 变成隐式依赖,难以测试
    • 传 nil context → panic
  3. context 取消后,ctx.Err() 可能返回什么?
    • context.Canceled(手动 cancel)
    • context.DeadlineExceeded(超时/截止)
    • nil(未取消)

三、Channel + Context 综合高频场景题

  1. 实现一个带超时的生产者-消费者(手撕)
  2. 用 context + channel 实现 worker pool(固定 goroutine 数量)
  3. 扇入/扇出模式(Fan-in / Fan-out) + context 传播取消
  4. 多个 goroutine 竞争同一个 channel,如何保证只消费一次?
  5. context 取消后,channel 还会继续发送吗?如何优雅处理?
  6. 用 select + context 实现非阻塞尝试发送/接收
  7. errgroup + context 组合使用的典型场景?
  8. context 为什么不能复用?(每次请求都要新派生)

四、2026 大厂真实追问方向(字节/阿里风格)

  • context 源码:cancel 如何传播?(链表 + atomic)
  • channel 底层实现:hchan 结构体、sudog、lock?
  • 无缓冲 channel vs 信号量(semaphore)?
  • channel + timer 实现超时机制 vs context.WithTimeout?
  • context.Value 的性能开销?为什么建议少用?
  • 如何用 channel 实现类似 mutex 的互斥?(不推荐,但考点)

建议刷题节奏
先把 1-12 题全部默写 + 解释清楚 → 再手写 3-5 个带 context 的完整并发模式(worker pool、超时控制、扇出)→ 最后看源码(context.go / runtime/chan.go)。

有哪道题想看详细代码实现、或想针对某个大厂风格加深(比如字节的 context 泄漏题、阿里的 fan-out 题),直接告诉我,我继续出题/拆解!

文章已创建 4298

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部