我有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
}
我只想确保我正确地处理了错误和错误,所以我的两个主要问题是:
在findDog中,两种情况下我是否都适当返回nil?
在sampleFunction中,不显式检查u!= nil是否很常见,或者我只是完全错误地执行了此操作?
我的目标是在程序员需要时正确地显示错误/问题,并在需要时向用户显示错误/问题,同时还要遵循惯用的标准。谢谢您的宝贵时间。
答案 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()
可能会失败