面试题答案
一键面试- 使用
recover
捕获panic
的原理:- 在Go语言中,
recover
函数只能在defer
函数中使用,用于捕获panic
并恢复程序的正常执行流。当panic
发生时,函数的执行会立即停止,函数中的defer
语句会按照后进先出的顺序执行,如果在defer
函数中调用recover
,就可以捕获到panic
的值,从而避免程序崩溃。
- 在Go语言中,
- 将错误信息记录到日志文件:
- 可以使用Go标准库中的
log
包来记录日志。在捕获到panic
后,将相关信息(如panic
的值、时间等)写入日志文件。
- 可以使用Go标准库中的
- 关键代码示例:
package main
import (
"log"
"os"
)
func main() {
defer func() {
if r := recover(); r!= nil {
// 打开日志文件,这里假设日志文件名为panic.log
file, err := os.OpenFile("panic.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err!= nil {
log.Println("Failed to open log file:", err)
return
}
defer file.Close()
logger := log.New(file, "", log.LstdFlags)
logger.Printf("Panic occurred: %v\n", r)
}
}()
// 模拟可能发生panic的操作,例如数据库连接中断
panic("Database connection lost")
}
在实际的微服务场景中,main
函数中的业务逻辑可能是具体的服务处理函数,比如处理HTTP请求的函数。例如:
package main
import (
"log"
"net/http"
)
func handleRequest(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r!= nil {
// 打开日志文件,这里假设日志文件名为panic.log
file, err := os.OpenFile("panic.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err!= nil {
log.Println("Failed to open log file:", err)
return
}
defer file.Close()
logger := log.New(file, "", log.LstdFlags)
logger.Printf("Panic occurred in request handling: %v\n", r)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
// 模拟可能发生panic的数据库操作
// 这里假设是一个数据库查询操作
// 实际中可能是使用数据库连接池进行查询
// 例如:
// rows, err := db.Query("SELECT * FROM some_table")
// if err!= nil {
// panic("Database query error: " + err.Error())
// }
// 这里简单模拟一个panic
panic("Database query error")
}
func main() {
http.HandleFunc("/", handleRequest)
log.Fatal(http.ListenAndServe(":8080", nil))
}
通过以上方式,在大规模Go语言微服务系统中,当某个服务发生panic
时,可以捕获panic
,记录相关错误信息到日志文件,并保证服务能继续运行(对于HTTP服务,能继续处理后续请求,只是对发生panic
的请求返回错误响应)。