面试题答案
一键面试实现思路
- 资源管理:为每个异步请求分配的资源,如文件描述符,应使用合适的数据结构进行跟踪,例如一个
map
,键为请求标识,值为对应的资源。 - 错误处理:每个异步请求的
goroutine
应使用defer
语句来确保无论是否发生错误,资源都能被释放。同时,通过channel
来传递错误信息。 - 全局资源清理:当有请求发生错误时,主
goroutine
需要负责清理所有相关资源,这可能涉及遍历资源跟踪数据结构并释放所有资源。
关键代码片段
package main
import (
"fmt"
"sync"
)
// 假设这是一个模拟资源的结构体
type Resource struct {
// 这里可以添加实际资源相关的字段,比如文件描述符等
}
func (r *Resource) Close() {
// 实现释放资源的逻辑
fmt.Println("Resource released")
}
func main() {
var wg sync.WaitGroup
resourceMap := make(map[int]*Resource)
errorCh := make(chan int, 10) // 用于传递发生错误的请求标识
// 模拟多个异步请求
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
res := &Resource{}
resourceMap[id] = res
defer func() {
if res != nil {
res.Close()
delete(resourceMap, id)
}
}()
// 模拟网络请求
if id == 1 {
errorCh <- id // 模拟请求1发生错误
return
}
fmt.Printf("Request %d completed successfully\n", id)
}(i)
}
go func() {
wg.Wait()
close(errorCh)
}()
// 处理错误并清理资源
for errID := range errorCh {
fmt.Printf("Error in request %d, cleaning up all resources\n", errID)
for id, res := range resourceMap {
res.Close()
delete(resourceMap, id)
}
}
}
在上述代码中:
Resource
结构体模拟了请求可能占用的资源,Close
方法用于释放资源。resourceMap
用于跟踪每个请求对应的资源。- 每个
goroutine
在执行请求前创建资源并添加到resourceMap
,使用defer
确保即使请求出错也能释放资源。 - 当某个请求发生错误时,通过
errorCh
传递错误标识,主goroutine
从errorCh
接收错误标识,并清理所有资源。