面试题答案
一键面试设计思路
- 使用defer和recover:在每个可能引发资源竞争导致panic的goroutine中,使用
defer
语句注册一个函数,在该函数中使用recover
来捕获panic。 - 错误处理:捕获到panic后,记录错误信息,确保不影响其他goroutine的正常运行。
- 防止内存泄漏:确保所有的资源(如文件描述符、网络连接等)都能正确关闭或释放。
核心代码片段
package main
import (
"fmt"
"log"
)
// 共享资源
var sharedResource int
func worker(id int) {
defer func() {
if r := recover(); r != nil {
// 捕获panic并记录错误
log.Printf("Goroutine %d panicked: %v", id, r)
}
}()
// 模拟资源竞争
for i := 0; i < 10; i++ {
sharedResource++
// 模拟可能引发panic的操作
if sharedResource > 10 {
panic("Data inconsistency")
}
fmt.Printf("Goroutine %d: sharedResource = %d\n", id, sharedResource)
}
}
func main() {
// 启动多个goroutine
for i := 0; i < 3; i++ {
go worker(i)
}
// 防止主线程退出
select {}
}
在上述代码中:
worker
函数中使用defer
注册了一个匿名函数,该函数使用recover
捕获可能的panic。- 如果捕获到panic,使用
log.Printf
记录错误信息,这样其他goroutine不会受到影响。 - 代码中虽然没有显式处理资源释放(因为示例简单),但在实际应用中,打开的资源应在
defer
中正确关闭,以防止内存泄漏。例如,如果有文件操作,在defer
中调用file.Close()
。