Historical reference on why Go creators choose to not treat `nil` as `false`

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

Historical reference on why Go creators choose to not treat `nil` as `false`

问题

为什么Go语言的创建者选择不将nil视为false?为什么他们认为明确比较值与nil更好?是否有可靠的来源可以解释为什么Go语言这样设计?他们的观点是什么?这个决策背后的逻辑是什么?

我正在寻找一个历史参考。


例如:

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

而不是像其他许多语言那样将nil隐式转换为false

f, err := os.Open(name)
if err {
    return err
}

目前,后者会报错:

non-bool err (type error) used as if condition
英文:

Why did Go creators choose to not treat nil as false? What why did they think it is better to explicitly compare values to nil? Is there a reliable source that would explain why is that is Go? What was their opinion? What was the logic behind this decision?

I'm looking for a historical reference.


E.g.:

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

Than to implicitly cast nils to false like in many other languages:

f, err := os.Open(name)
if err {
    return err
}

As of now, the latter would give:

non-bool err (type error) used as if condition

答案1

得分: 12

一些语言这样做会引起很多问题。这主要违反了最小惊讶原则。其中一些问题包括:

  • 所有非空值都会被评估为true。指向false布尔值的指针将被评估为true。所有这些都会引发新的、更复杂的问题,也就是更多的错误。
  • 将布尔值赋值为nil将是有效的。将布尔值与nil进行比较也是有效的。这会造成语义混淆。更多的错误。
  • 代码会变得更难阅读,因为它隐藏了意图。从表达式中无法判断你是想检查布尔值的值,还是断言其他类型变量的“非空性”。更多的错误。
  • 在表达式中省略比较操作数也可以编译通过,这使得识别错误变得更加困难。想想那种你忘记添加比较操作而导致b始终评估为true的情况,即使这不是你的本意。越来越多的错误。

Go语言的开发者可能考虑到了这些问题,并认为代码中错误较少的情况更好。

不过,也可以通过将错误传递给调用者来简化处理,例如:

require f := os.Open(name)
// 如果调用返回错误,返回错误

编辑:我很高兴地报告,Go团队正在考虑我提出的一个非常类似的方法,在Go 2中。只是他们使用了关键字check

check f := os.Open(name)
// 如果调用返回错误,运行声明的错误处理程序
// 这个处理程序可以返回错误或者对错误进行其他处理。
英文:

Some languages did that and it caused too many problems. It's primarily a violation of principle of least surprise. Some of the problems are:

  • All non-nil values would evaluate to true. A pointer to false boolean value would evaluate to true. All of that would create new and larger set of complications, aka more bugs.
  • Assigning a boolean to nil would be valid. Comparing a boolean to nil would be valid. That creates a semantic confusion. More bugs.
  • Code would be harder to read because it hides the intent. It's impossible to tell from an expression if you want to check a boolean's value or assert "non-nilness" of some other type of variable. More bugs.
  • Omitted operands in comparison operations in expressions would compile fine, making identifying bugs harder. Think about if a == '3' && b { .. } kind of cases where you forget to add the comparison so b always evaluates to true even if it's not what you intend. More and more bugs.

Go people probably thought about it and preferred code with less bugs is better.

There could be a shortcut though just to propagate the error to the caller such as:

require f := os.Open(name)
// if the call returns error, return error 

EDIT: I'm happy to report that Go team is considering a very similar approach to what I suggested, in Go 2. Only they used the keyword check instead:

check f := os.Open(name)
// if the call returns error run the declared error handler 
// which in turn, can return the error or do something else about it.

答案2

得分: 1

尽管我在任何golang文档或开发者讨论中都找不到确切的原因,但最接近的原因是,空值(nil)不应该被解释为假。这也符合golang是一种非常有主见的语言的事实,它的作者认为在评估真/假时不进行类型转换会导致更高质量的代码。

英文:

While I can't find an exact reason in any of the golang documentation or developer discussions, the closest reason is simply that that absence of a value (nil) should not be interpreted as false. This is also in line with the fact that golang is a very opinionated language, and that its authors felt that not casting types when evaluating for true/false would lead to better quality of code.

huangapple
  • 本文由 发表于 2016年4月26日 10:01:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/36854094.html
匿名

发表评论

匿名网友

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

确定