是否应该将 return err 放入带有声明的 if 语句的 else 中,或者避免这种样式并为 Golang 缩进 return?

Should return err be put in else for if statement with declaration or avoid this style and outdent the return for Golang?

在 Go 中,我们经常在 if 语句和 return err 中编写带有声明的代码。像这样:

    if res, err := getResult(); err != nil {
        return err
    } else {
        fmt.Println(res)
        // do something with res
    }

但是 linter 总是告诉我应该在 return:

之后删除 else
  ⚠  https://revive.run/r#indent-error-flow  if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)

代码段应如下所示以满足建议:

    res, err := getResult()
    if err != nil {
        return err
    }
    fmt.Println(res)
    // do something with res

看来我们应该避免在if语句中使用声明。

那么正确的围棋风格是怎样的呢?我应该如何处理 if 语句中的声明?

来自uber's go style guide 代码应尽可能减少嵌套。 例如:

if a {
    return a
} else {
    return b
}

是一种糟糕的代码编写方式。也应该删除这个不必要的 else。

此外,如果您需要 if 块之后的变量,则无需使用 if 块声明它们。 你可以浏览 uber 的 go 风格文档,这将帮助你编写优雅的 go 代码。

section about if in Effective Go 对此提供了一些指导:

The code reads well if the successful flow of control runs down the page, eliminating error cases as they arise. Since error cases tend to end in return statements, the resulting code needs no else statements.

f, err := os.Open(name)
if err != nil {
  return err
}
d, err := f.Stat()
if err != nil {
  f.Close()
  return err
}
codeUsing(f, d)

如果你坚持这种风格,如果你打算在你的“快乐之路”中使用非error结果,你根本不能将函数的结果声明为the simple statement that can precede the condition of the if statement中的变量;您别无选择,只能将该变量声明 放在 if 之前。然而,在函数只有 returns 和 error 的情况下(或者您不关心它的其他结果),您可以自由地将变量声明放在 if 中:

// within some HTTP handler
var u User
dec := json.NewDecoder(w)
if err := dec.Decode(&u) {
   w.WriteHeader(http.StatusBadRequest)
   return
}
// use u

关于流控的GO官方教程可以查看:https://go.dev/tour/flowcontrol/7

func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
    return v
} else {
    fmt.Printf("%g >= %g\n", v, lim)
}
// can't use v here, though
return lim
}