面试题答案
一键面试协程泄漏检测方法
- 使用 context.Context:
- 在启动协程时传入
context.Context
,通过context
的取消机制来通知协程结束。例如:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() go func(ctx context.Context) { for { select { case <-ctx.Done(): return default: // 协程执行的工作 } } }(ctx)
- 在启动协程时传入
- 使用 sync.WaitGroup:
- 记录启动的协程数量,在协程结束时递减
WaitGroup
的计数器。例如:
var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func() { defer wg.Done() // 协程执行的工作 }() } wg.Wait()
- 记录启动的协程数量,在协程结束时递减
- 第三方工具:
- 例如
go vet
可以检测出一些可能的协程泄漏情况,它能发现未使用的context
取消函数等问题。
- 例如
内存管理策略
- 对象池:
- 使用
sync.Pool
来复用对象,减少内存分配和垃圾回收压力。例如:
var bufPool = sync.Pool{ New: func() interface{} { return make([]byte, 1024) }, } buf := bufPool.Get().([]byte) // 使用buf bufPool.Put(buf)
- 使用
- 合理的结构体设计:
- 避免结构体中包含不必要的大字段,减少内存占用。如果某些字段在大部分情况下不需要,可以考虑使用指针类型,按需分配内存。
- 及时释放资源:
- 对于打开的文件、数据库连接等资源,使用
defer
语句及时关闭,例如:
file, err := os.Open("test.txt") if err != nil { // 处理错误 } defer file.Close()
- 对于打开的文件、数据库连接等资源,使用
优化调度以提高整体系统性能
- GOMAXPROCS 设置:
- 通过
runtime.GOMAXPROCS
函数设置同时执行的最大CPU数,根据服务器的CPU核心数合理调整。例如:
runtime.GOMAXPROCS(runtime.NumCPU())
- 通过
- 减少锁争用:
- 尽量避免在高并发场景下使用锁,如果必须使用,可以采用读写锁(
sync.RWMutex
),读多写少场景下能提高性能。并且缩小锁的保护范围,只在必要的数据操作时加锁。
- 尽量避免在高并发场景下使用锁,如果必须使用,可以采用读写锁(
- 任务切分与优先级调度:
- 将大任务切分成多个小任务,合理分配到不同的协程中执行。可以实现一个简单的优先级调度器,优先处理重要的任务。例如,使用带优先级的消息队列,协程从队列中按优先级获取任务执行。