- A: nil切片和空切片指向的地址一样吗?这个代码会输出什么?
- Q: nil切片和空切片指向的地址不一样。nil空切片引用数组指针地址为0(无指向任何实际地址)空切片的引用数组指针地址是有的,且固定为一个值
- A: 字符串转成byte数组,会发生内存拷贝吗?
- Q: 字符串转成切片,会产生拷贝。严格来说,只要是发生类型强转都会发生内存拷贝
- map的初始化容量 如果预计 map 会存储大量键值对,可以在初始化时指定容量,避免频繁扩容带来的性能开销
- slice深拷贝和浅拷贝
- 浅拷贝是指拷贝切片的引用,新切片和原切片共享同一个底层数组。修改一个切片的内容会影响另一个切片。(直接赋值切片变量)
- 深拷贝是指拷贝切片的数据内容,新切片拥有独立的底层数组,与原切片不共享内存。 通过手动拷贝数据实现深拷贝,例如使用 copy 函数。
- map触发扩容的时机,满足什么条件时扩容? - 已存储元素数 / 桶数 > 6.5 时触发扩容。 - 单个桶中链表的长度超过 8(键值对过多),会触发扩容。
扩容时会进行以下操作:
- 分配新桶数组
• 新桶的数量是当前桶数量的 2 倍。
• 扩容后,map 的容量变为原来的两倍,但数据并不会立即全部迁移。
- 增量迁移
• 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 |
| 通信模式 | 同步通信 | 异步通信 |
| 发送阻塞 | 如果没有接收方,会阻塞 | 如果缓存满,会阻塞 |
| 接收阻塞 | 如果没有发送方,会阻塞 | 如果缓存为空,会阻塞 |
| 适用场景 | 同步任务或严格控制通信顺序的场景 | 高并发、需要缓存数据的场景 |
协程通信方式有哪些?
-
- 使用 Channel 通信
-
- 使用全局变量加锁
-
- 使用 sync.WaitGroup
垃圾回收的过程是怎么样的? Go 的垃圾回收具有以下特点:
• 基于 标记-清除算法。
• 使用 三色标记法 保证并发时的安全性。
根对象(Roots :包括全局变量、当前栈上的局部变量和 CPU 寄存器中的变量,这些是 GC 开始扫描的入口。(STW:在标记阶段的开头和末尾,Go 运行时需要短暂暂停所有协程来执行一些关键操作,例如扫描根对象)
可达对象(Reachable Objects):通过根对象可以直接或间接访问的对象被认为是活跃的,不能被回收。
不可达对象(Unreachable Objects):不能通过根对象访问的对象被认为是垃圾,会被回收。
• 支持 并发和增量式回收,减少 STW 时间。
• 可通过 GOGC 环境变量调节性能和内存使用的平衡。
Goroutine 泄漏 是指程序中启动的 goroutine 在没有必要的情况下持续运行,且无法被垃圾回收。
为什么小对象多了会造成 gc 压力?
小对象多的情况下,GC 的扫描工作会增加,导致标记阶段的时间变长。