大家好,最近咱们训练营又有同学去挑战了字节跳动,这次是一面。
众所周知,字节的面试风格一向是“重基础、抠细节”,尤其是对语言底层原理(GMP、Map 机制)和中间件(Redis 数据结构)考察得非常细致。
今天我就把这次的面试题整理出来,去掉了个人项目相关的部分,只保留了通用的技术干货。如果你也想冲大厂,这份作业记得抄好!
【怎么回答】这题是开胃菜,但要答在点子上:
【怎么回答】主要对比开销和调度方式:
【怎么回答】select 类似于操作系统的 IO 多路复用(poll/epoll),但在 Go 里是用来处理多个 Channel 的操作。
time.After 实现超时处理。【怎么回答】记住 Go 的名言:“不要通过共享内存来通信,而要通过通信来共享内存。”Channel 就是这个“通信”的桥梁。它用于在不同的 Goroutine 之间安全地传递数据、同步状态以及进行任务编排(比如控制并发数、优雅退出等)。
【怎么回答】面试时如果一时想不起来“原语”这个词,就说 sync 包里的东西。
sync.Mutex(互斥锁)和 sync.RWMutex(读写锁)。sync.WaitGroup:等待一组协程完成。sync.Once:确保代码只执行一次(单例模式常用)。sync.Cond:条件变量,用于复杂的通知机制。sync.Pool:对象池,复用对象减少 GC。atomic 包:原子操作,性能比锁更高。【怎么回答】
sync.Map 并不适合所有并发场景,它最适合读多写少(Read map 命中率高)或者追加写(Key 只增不减)的场景。如果是频繁的读写混合,普通的 Mutex + map 性能可能更好。【怎么回答】这是字节必考题,必须烂熟于心:
【怎么回答】
【怎么回答】老三样套路:
select *,少做复杂的 Join。【怎么回答】这题考的是外部排序(External Sort),标准解法是归并排序。
【怎么回答】快排是面试手写的高频题,一定要能默写出来。核心是 Partition(分区)思想。
func quickSort(arr []int) []int {
iflen(arr) <= 1 {
return arr
}
pivot := arr[0] // 选基准值
var left, right []int
for _, v := range arr[1:] {
if v <= pivot {
left = append(left, v)
} else {
right = append(right, v)
}
}
// 递归:左 + 基准 + 右
returnappend(append(quickSort(left), pivot), quickSort(right)...)
}
// 注意:上面是易于理解的切片版本,面试最好写原地交换(In-place)版本节省空间
这轮面试虽然没有问特别偏门的架构设计,但在 Go 语言机制(GMP、Map)和数据结构(Redis Listpack、外排)上挖得比较深。
这也提醒我们:千万别只会调 API! 对于高频使用的数据结构和并发模型,一定要知道它底层是怎么跑的。多看源码,多看书(比如 Docker、K8S、MySQL 高级进阶),才能在字节这种大厂面试中游刃有余。
祝大家都能拿到心仪的 Offer!