MST

星途 面试题库

面试题:Go中recover与defer的协同机制

详细说明在Go语言里,recover和defer是如何协同工作的,为什么需要将recover放在defer函数中使用。假设你正在开发一个Web服务,在处理HTTP请求的函数中,怎样利用recover和defer来确保在发生panic时,既能够记录错误日志,又能正确地向客户端返回一个友好的错误响应,给出具体代码实现。
23.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. recover 和 defer 的协同工作原理
    • defer:在Go语言中,defer语句用于延迟函数的执行。当包含defer语句的函数执行到结束时(正常结束或者因为panic异常结束),defer语句后面指定的函数会按照后进先出(LIFO)的顺序依次执行。
    • recoverrecover是一个内置函数,用于终止panic造成的程序崩溃。它只能在defer修饰的函数中有效。当panic发生时,程序会立即停止当前函数的执行,开始执行defer函数,若在defer函数中调用recover,它会捕获到panic时传入的参数,从而使程序从panic状态中恢复,继续执行后续代码。
  2. 为什么将recover放在defer函数中使用
    • panic会立即终止当前函数的正常执行流程,直接执行defer函数。如果recover不放在defer函数中,panic发生时会跳过recover,导致程序崩溃。而在defer函数中,recover可以捕获到panic,并处理它,从而使程序恢复正常执行。
  3. Web服务处理HTTP请求利用recover和defer记录错误日志并返回友好响应的代码实现
package main

import (
    "fmt"
    "log"
    "net/http"
)

func handleRequest(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if err := recover(); err != nil {
            // 记录错误日志
            log.Printf("Panic occurred: %v", err)
            // 返回友好的错误响应
            http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        }
    }()
    // 模拟可能发生panic的代码
    panic("Simulated panic")
}

func main() {
    http.HandleFunc("/", handleRequest)
    log.Println("Server is running on http://localhost:8080")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("Server failed to start: ", err)
    }
}

在上述代码中:

  • defer函数在handleRequest函数结束时(无论是正常结束还是panic结束)都会执行。
  • recoverdefer函数中捕获panic,记录错误日志并向客户端返回一个HTTP 500错误响应。这样可以确保即使在处理HTTP请求时发生panic,程序也不会崩溃,而是能正确处理错误并向客户端返回友好的错误信息。