Go 如何温和地推迟可能返回错误的函数的执行?
大多数清理函数,特别是那些与IO操作相关的函数,都会返回一个Go 如何温和地推迟可能返回错误的函数的执行?,go,Go,大多数清理函数,特别是那些与IO操作相关的函数,都会返回一个错误,通常我们更愿意推迟执行它们,以防在处理完所获取的资源后忘记调用它们。例如,在代码中的某个时刻,我们可能会编写如下内容: var r *SomeResource var err error if r, err = Open(/* parameters */); err != nil { return nil, err } defer r.Close() // This might return an error 如果Clo
错误
,通常我们更愿意推迟执行它们,以防在处理完所获取的资源后忘记调用它们。例如,在代码中的某个时刻,我们可能会编写如下内容:
var r *SomeResource
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer r.Close() // This might return an error
如果Close
函数返回一个错误,它将被忽略。我们怎样才能温和地处理从这样一个函数返回的错误呢?像这样使用defer
和func(){}()
var r *SomeResource
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer func() {
if err = r.Close(); err != nil {
fmt.Printf("ERROR: %v", err)
}
}()
我们可以通过以下方式处理此问题:
way-1:
func myFn() error {
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer func() {
if cErr = r.Close(); cErr != nil {
err = cErr
}
}()
return err
}
func myFn() error {
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer func() {
if cErr = r.Close(); cErr != nil {
// we can log the error
// or
// whatever we want to do
}
}()
return err
}
way-2:
func myFn() error {
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer func() {
if cErr = r.Close(); cErr != nil {
err = cErr
}
}()
return err
}
func myFn() error {
var err error
if r, err = Open(/* parameters */); err != nil {
return nil, err
}
defer func() {
if cErr = r.Close(); cErr != nil {
// we can log the error
// or
// whatever we want to do
}
}()
return err
}
我还发现了一个关于这个主题的不错的博客,我的意思是当defer func返回错误时处理错误。检查此处。失败时会出现错误。报告第一个错误。不要覆盖以前的错误。比如说,
package main
import (
"fmt"
"os"
)
func demo() (name string, err error) {
filename := `test.file`
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer func() {
e := f.Close()
if e != nil {
if err == nil {
err = e
}
}
}()
// do someting with the file
name = f.Name()
fi, err := f.Stat()
if err != nil {
return name, err
}
if fi.Size() == 0 {
err = fmt.Errorf("%s: empty file", filename)
return name, err
}
return name, err
}
func main() {
name, err := demo()
fmt.Println(name, err)
}
这是一个有点过于固执己见的问题;您返回了一个错误,请随意处理!通常,这种类型的错误是您想要知道的,但不是您想要中断代码流的,因此您需要增加一个度量或编写一个日志行。正如Seaskyways的回答所说,您可以在闭包中编写此逻辑,或将其封装到帮助函数中。我认为它应该在函数中异常失败,而不是将错误返回到主例程。if e!=无{
defer中的这个检查可能是多余的,除了@zerkms所说的,这是正确的,带有命名返回参数的AFAIK,显式地指定return
参数,也是多余的。因此,在这个例子中,可以简单地编写return
而不是return name,err
。@Alirus你能做的事情并不能让它成为一个好的实践。根据codereview指南:“明确你的返回值。”可读性是最重要的。@Peters所以这可能是一个语言问题(我可能是母语人士)。我的观点是,如果删除该检查,则不会有任何改变。呃,我可能不是本地的speakerAlirus,请注意,没有任何东西会强迫您使用此处建议的匿名函数:拥有一个实用函数并安排在延迟调用中执行它是非常好的。OTOH,匿名函数通常使o如果需要,可以访问编码函数的返回变量。不过,使用此功能的实用性值得怀疑,因为它可能会妨碍对控制流的理解;请参阅@PeterSO提供的答案。