面试题答案
一键面试设计思路
- 封装文件处理函数:将文件处理逻辑封装在一个函数中,在这个函数内部使用
recover
捕获panic
。 - 使用
defer
机制:在文件处理函数内部使用defer
关键字,在defer
函数中进行recover
操作,这样无论函数正常结束还是因panic
结束,defer
函数都会被执行。 - 传递文件标识:在启动
goroutine
时,将文件的标识(如文件名、文件路径等)作为参数传递给文件处理函数,以便在panic
时能准确标识出对应的文件。 - 集中处理结果:使用一个通道(
channel
)来收集每个goroutine
的处理结果,包括正常结果和panic
信息。
可能用到的数据结构
- 结构体:用于封装文件处理结果和
panic
信息。
type FileProcessResult struct {
FilePath string
Success bool
ErrMsg string
}
- 通道(
channel
):用于在goroutine
之间传递处理结果。
resultChan := make(chan FileProcessResult)
代码示例
package main
import (
"fmt"
)
type FileProcessResult struct {
FilePath string
Success bool
ErrMsg string
}
func processFile(filePath string, resultChan chan FileProcessResult) {
defer func() {
if r := recover(); r != nil {
resultChan <- FileProcessResult{
FilePath: filePath,
Success: false,
ErrMsg: fmt.Sprintf("panic occurred: %v", r),
}
}
}()
// 模拟文件处理逻辑,这里可能会发生panic
if filePath == "corrupted_file.txt" {
panic("file corrupted")
}
// 文件处理成功
resultChan <- FileProcessResult{
FilePath: filePath,
Success: true,
ErrMsg: "",
}
}
func main() {
filePaths := []string{"file1.txt", "corrupted_file.txt", "file2.txt"}
resultChan := make(chan FileProcessResult)
for _, filePath := range filePaths {
go processFile(filePath, resultChan)
}
// 收集结果
for i := 0; i < len(filePaths); i++ {
result := <-resultChan
if result.Success {
fmt.Printf("File %s processed successfully\n", result.FilePath)
} else {
fmt.Printf("File %s processing failed: %s\n", result.FilePath, result.ErrMsg)
}
}
close(resultChan)
}
在上述代码中:
FileProcessResult
结构体用于存储文件处理结果和panic
信息。processFile
函数封装了文件处理逻辑,使用defer
和recover
捕获panic
,并将结果发送到resultChan
通道。main
函数启动多个goroutine
处理文件,并从resultChan
通道收集结果,根据结果判断文件处理是否成功。