go面试八股文

133 阅读4分钟
  • A: nil切片和空切片指向的地址一样吗?这个代码会输出什么?
  • Q: nil切片和空切片指向的地址不一样。nil空切片引用数组指针地址为0(无指向任何实际地址)空切片的引用数组指针地址是有的,且固定为一个值

  • A: 字符串转成byte数组,会发生内存拷贝吗?
  • Q: 字符串转成切片,会产生拷贝。严格来说,只要是发生类型强转都会发生内存拷贝

  • map的初始化容量 如果预计 map 会存储大量键值对,可以在初始化时指定容量,避免频繁扩容带来的性能开销

  • slice深拷贝和浅拷贝
  • 浅拷贝是指拷贝切片的引用,新切片和原切片共享同一个底层数组。修改一个切片的内容会影响另一个切片。(直接赋值切片变量)
  • 深拷贝是指拷贝切片的数据内容,新切片拥有独立的底层数组,与原切片不共享内存。 通过手动拷贝数据实现深拷贝,例如使用 copy 函数。

- map触发扩容的时机,满足什么条件时扩容? - 已存储元素数 / 桶数 > 6.5 时触发扩容。 - 单个桶中链表的长度超过 8(键值对过多),会触发扩容。

扩容时会进行以下操作:

  1. 分配新桶数组

• 新桶的数量是当前桶数量的 2 倍

• 扩容后,map 的容量变为原来的两倍,但数据并不会立即全部迁移。

  1. 增量迁移

• Go 的 map 使用增量迁移(incremental rehashing)来避免一次性扩容导致性能抖动。

• 每次对 map 进行读写操作时,迁移一小部分数据到新的桶中,直到迁移完成。


  • 对已经关闭的的chan进行读写,会怎么样?为什么?

  • 已经关闭的 chan 能一直读到东西,但是读到的内容根据通道内关闭前是否有元素而不同。

    • 如果 chan 关闭前,buffer 内有元素还未读 , 会正确读到 chan 内的值,且返回的第二个 bool 值(是否读成功)为 true
    • 如果 chan 关闭前,buffer 内有元素已经被读完chan 内无值,接下来所有接收的值都会非阻塞直接成功,返回 channel 元素的零值,但是第二个 bool 值一直为 false
  • 已经关闭的 chan 会 panic


未初始化的 channel进行读写,会发生什么?

  • 对 nil channel 的读写操作会永久阻塞。
  • 关闭 nil channel 会导致 pani

有缓存的channel和没有缓存的channel区别是什么?

标题有缓存的channel无缓存的channel
定义不指定容量或容量为 0指定容量大于 0
通信模式同步通信异步通信
发送阻塞如果没有接收方,会阻塞如果缓存满,会阻塞
接收阻塞如果没有发送方,会阻塞如果缓存为空,会阻塞
适用场景同步任务或严格控制通信顺序的场景高并发、需要缓存数据的场景

协程通信方式有哪些?

    1. 使用 Channel 通信
    1. 使用全局变量加锁
    1. 使用 sync.WaitGroup

垃圾回收的过程是怎么样的? Go 的垃圾回收具有以下特点:

• 基于 标记-清除算法

• 使用 三色标记法 保证并发时的安全性。

根对象(Roots :包括全局变量、当前栈上的局部变量和 CPU 寄存器中的变量,这些是 GC 开始扫描的入口。(STW:在标记阶段的开头和末尾,Go 运行时需要短暂暂停所有协程来执行一些关键操作,例如扫描根对象)

可达对象(Reachable Objects):通过根对象可以直接或间接访问的对象被认为是活跃的,不能被回收。

不可达对象(Unreachable Objects):不能通过根对象访问的对象被认为是垃圾,会被回收。

• 支持 并发和增量式回收,减少 STW 时间。

• 可通过 GOGC 环境变量调节性能和内存使用的平衡。


Goroutine 泄漏 是指程序中启动的 goroutine 在没有必要的情况下持续运行,且无法被垃圾回收。


为什么小对象多了会造成 gc 压力?

小对象多的情况下,GC 的扫描工作会增加,导致标记阶段的时间变长。