处理一个错误非常简单
1
2
3
4
5
6
7
8
| package main
func main() {
var err error
if err != nil {
// 处理错误
}
}
|
在一个返回错误的函数中处理也很简单
1
2
3
4
5
6
7
8
9
10
11
12
| package main
import "os"
func doSomething() error {
fd,err := os.Open("file.txt")
if err != nil {
return err
}
defer fd.Close()
// 对文件读写操作
return nil
}
|
但上面的处理方式有些问题
defer后面的文件关闭操作有可能会出错,此时调用方完全不知道发生了什么
更好的做法,参考知名项目的做法,例如 kubebuilder
返回值使用命名返回值,确保defer 中可以覆盖err
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| func (s Scaffold) loadModelFromFile(path string) (f *File, err error) {
reader, err := s.fs.Open(path)
if err != nil {
return nil, OpenFileError{err}
}
defer func() {
// 只有在函数主体正常,并且关闭文件错误时才会覆盖err
if closeErr := reader.Close(); err == nil && closeErr != nil {
err = CloseFileError{closeErr}
}
}()
content, err := afero.ReadAll(reader)
if err != nil {
return nil, ReadFileError{err}
}
return &File{Path: path, Contents: string(content)}, nil
}
|
更加完善的错误方式,可以在defer中使用 errors.Join 来合并错误