面试题答案
一键面试package main
import (
"fmt"
"os"
)
func readFileContent(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer func() {
closeErr := file.Close()
if closeErr != nil {
fmt.Printf("Error closing file: %v\n", closeErr)
}
}()
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
return string(content), nil
}
多返回值与defer协同工作解释
- 函数返回值:在Go语言中,函数可以返回多个值。在这个函数中,我们返回文件内容(
string
类型)和可能出现的错误(error
类型)。 - defer语句:
defer
语句用于延迟函数调用,它会在函数返回之前执行。在这里,我们使用defer
来关闭文件,确保无论函数在读取文件内容过程中是否发生错误,文件最终都会被关闭。即使在函数中提前返回(例如在os.Open
失败时),defer
语句中的file.Close()
仍然会被执行。
如果defer语句中也发生错误的处理
在上述代码中,当defer
语句执行file.Close()
时,如果关闭文件过程中发生错误,我们通过fmt.Printf
打印了错误信息。更优雅的处理方式可以是:
- 记录日志:使用日志库(如
log
包)记录错误,这样错误信息可以被更好地追踪和管理。 - 返回错误:如果关闭文件的错误非常严重,影响到程序的正确性,可以将这个错误返回给调用者。但是由于我们已经返回了读取文件内容的错误,这种情况下需要权衡如何更好地向调用者传达这两个错误信息,例如可以将关闭文件的错误附加到读取文件内容的错误信息中返回。
func readFileContentBetter(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
var closeErr error
defer func() {
closeErr = file.Close()
}()
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
if closeErr != nil {
return "", fmt.Errorf("read file success, but close file error: %v", closeErr)
}
return string(content), nil
}
这样,如果读取文件成功但关闭文件失败,调用者可以得到更详细的错误信息。