面试题答案
一键面试管理资源避免泄漏
- 使用
defer
关键字:在Go语言中,defer
语句用于注册在函数返回时执行的延迟调用。对于需要管理的资源(如文件句柄、数据库连接),可以在获取资源后立即使用defer
来确保在函数结束时正确关闭资源。 - 使用
context.Context
:context.Context
用于在不同的goroutine之间传递截止时间、取消信号等信息。在并发任务中,通过传递context.Context
,可以在任务被取消或者超时时,及时关闭相关资源。
异常捕获与处理
- 使用
sync.WaitGroup
和错误通道:在Future模式中,可以结合sync.WaitGroup
来等待所有goroutine完成,并通过一个错误通道来收集每个goroutine中的异常。 recover
机制:在goroutine内部,可以使用recover
来捕获panic
,并将其转换为普通错误进行处理。
示例代码
package main
import (
"context"
"fmt"
"io/ioutil"
"sync"
)
// Future 结构体模拟Future模式中的结果容器
type Future struct {
result interface{}
err error
}
// worker 函数模拟一个并发任务
func worker(ctx context.Context, wg *sync.WaitGroup, futureChan chan Future) {
defer wg.Done()
var future Future
// 模拟打开文件
file, err := ioutil.TempFile("", "example")
if err != nil {
future.err = err
futureChan <- future
return
}
defer file.Close()
// 模拟任务逻辑
select {
case <-ctx.Done():
future.err = ctx.Err()
default:
// 假设这里有实际的任务逻辑,设置result
future.result = "Task completed successfully"
}
futureChan <- future
}
func main() {
var wg sync.WaitGroup
futureChan := make(chan Future)
ctx, cancel := context.WithCancel(context.Background())
wg.Add(1)
go worker(ctx, &wg, futureChan)
go func() {
// 模拟在某个条件下取消任务
// 这里简单地在1秒后取消
select {
case <-ctx.Done():
case <-make(chan struct{}, 1):
cancel()
}
}()
go func() {
wg.Wait()
close(futureChan)
}()
for future := range futureChan {
if future.err != nil {
fmt.Printf("Error occurred: %v\n", future.err)
} else {
fmt.Printf("Result: %v\n", future.result)
}
}
}
在上述代码中:
- 资源管理:在
worker
函数中,使用defer file.Close()
来确保打开的临时文件在函数结束时被关闭。 - 异常处理:通过
context.Context
来模拟任务取消,并将取消的错误或者任务执行中的错误通过futureChan
传递到主函数进行处理。同时,主函数通过sync.WaitGroup
等待所有任务完成,并从futureChan
通道中获取每个任务的结果或者错误进行相应处理。