MST
星途 面试题库

面试题:Go中context如何用于控制资源释放时机

在Go语言中,简要描述context是如何帮助我们把控资源释放时机的?请举例说明在一个简单的HTTP服务函数中,如何利用context来控制数据库连接资源的及时释放。
27.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

1. context把控资源释放时机原理

在Go语言中,context通过携带截止时间、取消信号等信息,在多个goroutine之间传递。当父context被取消或超时时,所有基于该父context衍生的子context也会被取消,从而通知相关的goroutine及时停止工作并释放资源。

2. HTTP服务函数中利用context控制数据库连接资源释放示例

假设我们使用database/sql包连接MySQL数据库,示例代码如下:

package main

import (
    "context"
    "database/sql"
    "fmt"
    "net/http"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test")
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        // 创建一个带有取消功能的子context
        ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
        defer cancel()

        var result string
        err := db.QueryRowContext(ctx, "SELECT column_name FROM table_name WHERE some_condition").Scan(&result)
        if err != nil {
            if err == context.DeadlineExceeded {
                http.Error(w, "Database operation timed out", http.StatusGatewayTimeout)
            } else {
                http.Error(w, "Database query error", http.StatusInternalServerError)
            }
            return
        }

        fmt.Fprintf(w, "Result: %s", result)
    })

    http.ListenAndServe(":8080", nil)
}

在上述代码中:

  • 通过r.Context()获取HTTP请求的context
  • 使用context.WithTimeout创建一个带有超时的子context,并在函数结束时调用cancel函数,确保在函数返回前释放相关资源。
  • 在执行数据库查询时,使用db.QueryRowContext方法并传入context。如果context超时(例如数据库操作超过500毫秒),数据库操作会被取消,函数会返回错误,从而避免长时间占用数据库连接资源。