在Golang中处理零错误的惯用方式是什么?

时间:2018-09-23 02:58:05

标签: go error-handling

我有2个go函数:

func sampleFunction () {
    u, err := findDog(1)
    if err != nil {
        // We couldn't find the dog, print a message.
        fmt.Println(err)
        // Custom error types.
        if _, ok := err.(*dneError); ok {
            fmt.Println("Custom dog dne error for the end-user here.")
        }
    } else {
        // Do something with u.
        u.doSomething() // Is this idiomatic in Go?
                        // Should we explicility check for u != nil?
                        // Or does the if check above need to return?
                        // (even if I would like the function to be longer)

    }
}

// findDog returns a dog with a given ID. If not found, returns an error.
func findDog(id int) (*models.Dog, error) {
    found, err := models.FindDog(id)
    // Is this return scheme/flow too brittle?
    if err != nil {
        return nil, &dneError{fmt.Sprintf("Dog %d does not exist in the" +
            "database: %s", id, err.Error())}
    }
    return found, nil
}

我只想确保我正确地处理了错误和错误,所以我的两个主要问题是:

  1. 在findDog中,两种情况下我是否都适当返回nil?

  2. 在sampleFunction中,不显式检查u!= nil是否很常见,或者我只是完全错误地执行了此操作?

我的目标是在程序员需要时正确地显示错误/问题,并在需要时向用户显示错误/问题,同时还要遵循惯用的标准。谢谢您的宝贵时间。

2 个答案:

答案 0 :(得分:2)

是的,这是惯用的Go。由于错误是预先处理的,因此错误意味着发生了某些错误,结果是nil或例如。也许没有任何用处的部分编写的缓冲区。

P.S。我也有一个建议,可以使事情更加惯用。习惯用法类似于“缩进错误块,而不是代码”。您在sampleFunction中特别有一个if / else,但是在大多数错误检查情况下(不是全部),您将其处理并返回,然后跳过else,然后流程继续。为什么不必缩进?这具有使甚至很长的函数易于阅读的效果,因为该函数的预期流程可以从上至下读取,而不必在if / else块之间来回跳动。至少在很多情况下。

我对某人的存储库中的拉取请求进行了修改,因为我有一个if / else,其中if with return足够。

编辑 所以我的回答有点困扰我,现在我记得为什么。非nil error返回通常是惯用的,它表示其他返回值是无用的,但确实有例外。 请务必检查各个文档。

作为一个具体示例,请参见bytes.Buffer.ReadBytes

  

如果ReadBytes在找到定界符之前遇到错误,它将返回错误之前读取的数据和错误本身(通常为io.EOF)。

答案 1 :(得分:1)

我个人认为您处理得很好,只是一个建议,因为我不知道是什么models.FindDog(id),所以我会仔细检查found,如果这是nil,则返回错误,总结if err != nil || found == nil {

注意:这样做return err.Error()可能会失败