面试题答案
一键面试影响
- 应用崩溃:在Go中,默认情况下,一个
goroutine
发生panic
如果没有被捕获,会导致整个程序崩溃,所有正在运行的goroutine
都会被终止。 - 资源泄露:如果在发生
panic
时,一些资源(如文件句柄、数据库连接等)没有正确释放,会造成资源泄露。
设计思路
- 使用
recover
:在goroutine
内部使用defer
和recover
来捕获panic
。defer
语句会在函数返回或panic
时执行,recover
函数可以捕获到panic
并恢复程序的正常执行。 - 错误处理和日志记录:捕获
panic
后,将错误信息记录到日志中,便于排查问题。同时,可以根据具体情况决定如何处理错误,如重试操作、返回错误信息给调用者等。 - 资源管理:确保在捕获
panic
后,正确释放所有相关资源,避免资源泄露。 - 性能和资源利用:尽量减少在捕获
panic
过程中的额外开销,避免引入性能瓶颈。例如,日志记录应该是高效的,避免频繁的I/O操作。
关键代码示例
package main
import (
"fmt"
"log"
)
func worker() {
defer func() {
if r := recover(); r != nil {
// 记录错误日志
log.Printf("Panic occurred: %v", r)
// 处理错误,例如可以在这里进行重试逻辑等
}
}()
// 模拟资源耗尽导致panic
var data []int
for {
data = append(data, 1)
}
}
func main() {
go worker()
// 主goroutine可以继续执行其他任务
for i := 0; i < 10; i++ {
fmt.Println("Main goroutine is running:", i)
}
// 防止主程序退出
select {}
}
在上述代码中:
worker
函数使用defer
和recover
来捕获可能发生的panic
。main
函数启动了一个goroutine
来执行worker
函数,同时主goroutine
可以继续执行其他任务,不会因为worker
中的panic
而崩溃。- 捕获到
panic
后,通过log.Printf
记录错误信息。实际应用中,可以根据具体需求进行更详细的错误处理和资源管理。