Golang中哪种写法更符合语言习惯?
Golang中哪种写法更符合语言习惯? 这里存在两种惯用法之间的明显冲突:
- 逗号Ok惯用法与If语句:将变量的作用域限制在仅需要它们的地方,常用于错误处理和类型断言。
- 避免不必要的
else块:在if块以return语句结束时,避免使用else块,以减少嵌套并提高可读性。
逗号Ok惯用法
if bs, err := json.Marshal(b); err != nil {
handleError(w, err)
return
} else {
fmt.Fprintln(w, string(bs))
}
避免不必要的else
var bs []byte
if bs, err = json.Marshal(b); err != nil {
handleError(w, err)
return
}
fmt.Fprintln(w, string(bs))
将“bs”移到if语句之外/之上会扩大其作用域,并可能导致错误。
Golint 支持第二种惯用法:
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)
注意事项
- 上下文很重要。对于较小的函数,变量作用域的扩大不会显著增加复杂性或风险,此时通过避免不必要的
else块来简化控制流可能是首选。在更复杂的函数中,或者当一个变量确实不应该在特定代码块之外被访问时,保持更严格的作用域可能被优先考虑。 golint基于常见的最佳实践提供建议,但它并不涵盖所有可能的代码上下文或细微差别。它是一个辅助开发的工具,而不是一套必须在所有情况下严格遵守的规则。
那么,Golint 是否因此成为权威答案,使得第二种选择是更地道的做法?
更多关于Golang中哪种写法更符合语言习惯?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我通常这样写:
bs, err := json.Marshal(b)
if err != nil {
handleError(w, err)
return
}
fmt.Fprintln(w, string(bs))
更多关于Golang中哪种写法更符合语言习惯?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
根据我阅读Go代码的经验,这绝对是处理这类事情最常见的方式。
我仅在函数除了错误没有其他返回值时,才会使用方法1。
if err := doSomething(); err != nil {
// 处理错误
}
说实话,我从未见过有人使用方法2。
Dean_Davidson:
这非常符合 Go 语言的惯用法,如果你查看 Go 的源代码,你会发现它随处可见。
谢谢!我怎么就没想到去标准库里找找例子呢?虽然里面也有一些相当奇特的例子(没错,sort 包,我说的就是你!)。
感谢回复!
这似乎是一种非常流行的做法。其好处在于,通过使用 bs 的简短声明,代码变得简单明了,并且无需查找和指定其类型(类似于我帖子中的选项 #1)。其代价是,这也扩大了 err 的作用域。
Massimo.Costa:
好吧,根据我阅读Go代码的经验,这绝对是处理这类事情最常见的方式。
谢谢!
这是我之前没有考虑到的一点。是否采用惯用方式取决于你是否需要对“逗号,Ok”惯用法中涉及的变量的返回值进行进一步处理。
这是一种非常地道的写法,如果你查看 Go 的源代码,会发现这种写法随处可见。例如在 encoding/json 中:
// convertNumber converts the number literal s to a float64 or a Number
// depending on the setting of d.useNumber.
func (d *decodeState) convertNumber(s string) (any, error) {
if d.useNumber {
return Number(s), nil
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeFor[float64](), Offset: int64(d.off)}
}
return f, nil
}
在Go语言中,第二种写法(避免不必要的else)更符合惯用法。Go社区普遍遵循“尽早返回”的模式,这有助于减少嵌套、提高代码可读性。golint的建议反映了这一共识,但工具本身并非绝对权威,代码的可维护性和清晰度才是关键。
示例代码:
// 更地道的写法
func handleData(w http.ResponseWriter, b interface{}) {
bs, err := json.Marshal(b)
if err != nil {
handleError(w, err)
return
}
fmt.Fprintln(w, string(bs))
}
如果需要在条件判断中初始化变量,可以这样写:
func processData(data interface{}) error {
if bs, err := json.Marshal(data); err != nil {
return err
} else {
// 使用bs
_ = bs
}
return nil
}
但更推荐将变量声明移到if外部:
func processData(data interface{}) error {
bs, err := json.Marshal(data)
if err != nil {
return err
}
// 使用bs
_ = bs
return nil
}
对于错误处理,Go的典型模式是:
value, ok := someMap[key]
if !ok {
return errors.New("key not found")
}
// 使用value
这种模式将错误检查放在前面,正常逻辑放在后面,避免了深层嵌套。

