Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何温和地推迟可能返回错误的函数的执行?_Go - Fatal编程技术网

Go 如何温和地推迟可能返回错误的函数的执行?

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

大多数清理函数,特别是那些与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

如果
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提供的答案。