MST

星途 面试题库

面试题:Go中context的超时机制与资源释放

在一个使用Go语言编写的网络爬虫程序中,使用`context`设置了10秒的超时。在爬虫的并发请求处理函数中,可能会打开文件句柄用于记录数据,或者建立数据库连接等资源操作。请阐述如何利用`context`的超时机制,确保在超时发生时,所有已经打开的资源(如文件句柄、数据库连接)能够被正确关闭和释放,避免资源泄漏。
50.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 使用context.WithTimeout创建带超时的context
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    这里创建了一个ctx,它在10秒后会自动取消,cancel函数用于手动取消(如果需要提前取消的话),使用defer确保函数结束时一定会调用cancel,防止资源泄漏。
  2. 在并发请求处理函数中传递context
    var wg sync.WaitGroup
    for _, url := range urls {
        wg.Add(1)
        go func(u string) {
            defer wg.Done()
            processURL(ctx, u)
        }(url)
    }
    wg.Wait()
    
    这里processURL函数接收ctx作为参数,wg用于等待所有并发任务完成。
  3. processURL函数中处理资源操作
    func processURL(ctx context.Context, url string) {
        // 打开文件句柄
        file, err := os.OpenFile("log.txt", os.O_CREATE|os.O_WRONLY, 0644)
        if err!= nil {
            log.Println("Failed to open file:", err)
            return
        }
        defer file.Close()
    
        // 建立数据库连接(示例,实际需要根据具体数据库驱动调整)
        db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/database")
        if err!= nil {
            log.Println("Failed to connect to database:", err)
            return
        }
        defer db.Close()
    
        // 模拟请求
        req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
        if err!= nil {
            log.Println("Failed to create request:", err)
            return
        }
        resp, err := http.DefaultClient.Do(req)
        if err!= nil {
            if ctx.Err() == context.DeadlineExceeded {
                log.Println("Request timed out")
            } else {
                log.Println("Failed to do request:", err)
            }
            return
        }
        defer resp.Body.Close()
    
        // 处理响应数据,写入文件等操作
        //...
    }
    
    • 在打开文件句柄和建立数据库连接后,使用defer语句确保函数结束时文件和数据库连接会被关闭。
    • 在发起HTTP请求时,使用http.NewRequestWithContextctx传递进去,这样如果ctx超时,请求也会被取消。
    • 当发生错误时,检查ctx.Err()是否为context.DeadlineExceeded,如果是,则表示是超时错误,做相应处理。

通过上述步骤,利用context的超时机制,结合defer语句关闭资源,可以确保在超时发生时,所有已经打开的资源能够被正确关闭和释放,避免资源泄漏。