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

huangapple go评论83阅读模式
英文:

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)
		// 对res进行一些操作
	}

但是代码检查工具总是告诉我在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)
	// 对res进行一些操作

看起来我们应该避免在if语句中进行声明。

那么什么是正确的Go风格?在if语句中进行声明时应该怎么做呢?

英文:

In Go, we often write code with declaration in if statement and also return err. Like this:

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

But the linter always tells me should drop the else block after return:

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

The code snippet should looks like this to meet the suggestion:

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

It seems that we should avoid to use the declaration in if statements.

So what is the correct Go style? And what should I do with the declaration in if statements?

答案1

得分: 4

在《Effective Go》中关于if的部分提供了一些指导:

如果代码的控制流畅畅地向下运行,随着错误情况的出现而消除,那么代码的可读性就很好。由于错误情况往往以return语句结束,所以最终的代码不需要else语句。

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结果,那么你就不能将函数的结果声明为if语句条件之前的变量,你只能将变量声明放在if之前。然而,在函数只返回一个error的情况下(或者你不关心其它结果),你可以将变量声明放在if中:

// 在某个HTTP处理程序中
var u User
dec := json.NewDecoder(w)
if err := dec.Decode(&u) {
   w.WriteHeader(http.StatusBadRequest)
   return
}
// 使用u
英文:

The section about if in Effective Go provides some guidance about this:

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

If you adhere to this style, and if you intend to use the non-error results in your "happy path", you simply cannot declare the function's results as variables in the simple statement that can precede the condition of the if statement; you have no choice but to put that variable declaration before the if. However, in cases where the function only returns an error (or you don't care about its other results), you're free to put the variable declaration in the if:

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

答案2

得分: 0

Uber的Go风格指南中,代码应尽量减少嵌套。例如:

if a {
	return a
} else {
	return b
}

这种写法是不好的。而且这个不必要的else应该被移除。

另外,如果你需要在if块之后使用变量,不需要在if块中声明它们。你可以参考Uber的Go风格文档,它将帮助你编写优雅的Go代码。

英文:

From uber's go style guide code should reduce nesting as much as possible.
For example:

if a {
	return a
} else {
	return b
}

is a bad way of writing code. Also this unnecessary else should be removed.

Also if you need the variables after the if block it's not necessary to declare them with if block.
You may go through the uber's go style doc which will help you to write elegant go code.

答案3

得分: 0

你可以在官方的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)
    }
    // 不能在这里使用v
    return lim
}
英文:

You can check official GO tutorial on flow control: https://go.dev/tour/flowcontrol/7

func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v &lt; lim {
	return v
} else {
	fmt.Printf(&quot;%g &gt;= %g\n&quot;, v, lim)
}
// can&#39;t use v here, though
return lim
}

huangapple
  • 本文由 发表于 2021年12月28日 23:53:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/70509411.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定