如何缓缓执行可能返回错误的函数?

时间:2018-11-26 18:40:41

标签: go

大多数清除功能,特别是与IO操作相关的功能,都会返回error,通常,我们更愿意defer执行它们,以防万一我们在调用时不忘调用它们用获得的资源完成。例如,在代码中的某些时候,我们可能会编写如下代码:

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函数返回错误,它将被忽略。我们如何才能从这样的函数中轻轻地处理返回的error

3 个答案:

答案 0 :(得分:6)

像这样将deferfunc() {}()一起使用。

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)
    }
}()

答案 1 :(得分:3)

错误地正常失败。报告第一个错误。不要覆盖以前的错误。例如,

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)
}

答案 2 :(得分:-1)

我们可以通过以下方式处理此问题:

方式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
}

方式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 {
            // we can log the error
            // or
            // whatever we want to do
        }
    }()
    return err
}

我也在这个主题上找到了一个不错的博客,我的意思是当defer func返回错误时处理错误。在这里https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-iii-36a1ab3d6ef1中检查。