【问题标题】:Why does Golang enforce curly bracket to not be on the next line?为什么 Golang 强制大括号不在下一行?
【发布时间】:2013-06-13 18:43:02
【问题描述】:

正确:

if(true) {

}

不正确:

if(true)
{

}

为什么要强制执行这种风格,是否与语言规范有关,或者仅仅是因为他们更喜欢一种风格而不是另一种风格?

【问题讨论】:

  • go 的编译器会自动为你输入所有分号。在不正确的版本中,它会在 if(true);{} 之后添加分号,这样是不正确的。
  • 第一个版本在语法上是正确的,但在风格上很糟糕。除非需要,否则应使用()。见Effective Go
  • @deft_code 这一点意义都没有。你怎么能不在需要的地方使用 (),这是自相矛盾的。
  • @deft_code 你写的是“应该”而不是“不应该”
  • @Neutrino,对于 C 将 { 替换为 then 和将 } 替换为 end 也可以这样说。然后你可以编写可读的 C。我认为 Go 设计者做出了一个伟大的决定来结束神圣风格的战争。 Go 应该只有一种风格,它应该有一种风格。一应是其计数的大小。阿门。 这个想法已经引起了人们的注意,自从 Go 在 Google 自动格式化程序中的普及以来,我们已经为我们使用的大多数语言编写了该程序。我不会错过能够自定义代码的缩进/空白样式。

标签: coding-style go curly-braces


【解决方案1】:

为什么有大括号但没有分号?为什么我不能把左大括号放在下一行?

Go 使用大括号进行语句分组,这是使用过 C 家族任何语言的程序员所熟悉的语法。然而,分号是用于解析器的,而不是用于人的,我们希望尽可能地消除它们。为了实现这个目标,Go 借鉴了 BCPL 的一个技巧:分隔语句的分号在形式语法中,但在可能是语句结尾的任何行的末尾由词法分析器自动注入,无需前瞻。这在实践中非常有效,但它的效果是强制使用大括号样式。例如,函数的左大括号不能单独出现在一行中。

http://golang.org/doc/faq#semicolons

【讨论】:

  • 如果它强制使用大括号样式,这首先破坏了使用大括号的意义(即,使大括号排列在同一列上的语句块的范围易于识别),那么这几乎不可能被描述为“工作得很好”。如果这意味着我可以合理地排列大括号,我个人更愿意手动添加分号。治愈比疾病更糟糕的完美例子。
  • @Neutrino:我怀疑 Go 语言的设计者认为风格强制是一件好事。 “约束正在解放。”
  • 他们的借口是假的。 Lua 一直使用分号来表示代码块,并且在 Go 出现之前就不需要分号。他们可以允许支持其他大括号样式,但他们明确选择不支持。无论是为了让他们在解析中作弊,还是因为他们决定将他们的个人偏好强加于用户群,这两个原因都是将用户锁定为单一括号样式的不好理由。
  • @Pharap:更不用说,换行上的大括号是 ANSI 标准。 K&R 不是。但标准的美妙之处在于有很多不同的标准。 InternetExplorer 就是一个很好的例子。此外,强制执行样式以便更好地打印代码是愚蠢的。他们应该强制执行一种样式,以最大程度地阻止您首先将代码打印在纸上。打印代码是愚蠢的(你想实现什么?备份?),这是一个安全风险,更不用说环境问题了。此外,如果您想拥有特定格式的代码,请编写美化器。
  • @StefanSteiger Meh。我在纸上打印了代码,因为它更容易清除以进行调试、解决复杂问题或简单地红笔。您对愚蠢的看法非常苛刻和固执己见。 #justsayin。
【解决方案2】:

大多数C 派生语言使用if ( <condition> ) <statement> 样式,如果condition 为真,则执行statementstatement 可以是单个语句或大括号括起来的块。

Go 的 if 语句需要后面的大括号括起来的块,而不是单个语句。这是为了阻止common error,大多数样式指南都要求所有if 语句都使用大括号来避免这种情况。

//subtle error in C
if (<condition>)
  <statement1>;
  <statement2>;

既然 Go 需要在 if 语句之后使用大括号块,那么 () 是多余的。它们仅用于帮助词法分析器区分条件和语句,否则 if &lt;condition&gt; &lt;statement&gt; 很难解析。 (条件在哪里结束,语句从哪里开始?)

现在 Go 的作者有一个决定:

  • 保留多余的()
  • 要求{ 关注&lt;condition&gt;

他们认为冗余是不可取的。这有第二个副作用。由于每个换行符都有一个隐含的;,如果{ 在下一行,则; 将放在&lt;condition&gt;{ 之间。 Go 的作者再次面临一个决定:

  • 特殊情况下,解析器对&lt;condition&gt;; { 构造更智能
  • 要求大家在同一行采用if ... {的共同风格。
  • 要求&lt;condition&gt; 位于一行。

解析器的特殊外壳是一个非常坏事。看看速度 D 和 Go 解析器与 C++ 糟糕的解析器性能相比。统一的风格也是一件好事。考虑到这些限制,他们的最终决定非常简单。

【讨论】:

  • 为什么要和 d 和 c++ 比较?他们没有隐含的;
  • Go 的 ; 插入使用非前瞻词法分析器。这真的很快。出于性能考虑,隐式; 与显式; 一样快。 D、C++、Java、C#、Go 在其语法规范中都使用 ;,它们是 C后代(又名大括号语言)。我比较它们是因为它们的解析器相似并且必须解决相似的问题。
  • 为什么不直接写机器码呢?编程语言的目的是使程序易于人类而不是机器阅读。编译器的目的是让机器高效地执行代码。我不在乎解析很慢。那些括号对人眼没有帮助。 Python 在这里更加连贯。
  • 大括号确实对人眼有帮助,而 Python 的重要空白是一个糟糕的设计选择。程序员不必自己缩进代码,这应该由代码格式化工具自动完成。
【解决方案3】:

这与 Spec 有关,也就是说,这不仅仅是他们在编译器中内置的东西

分号

形式语法使用分号“;”作为许多终结者 制作。 Go 程序可以使用 遵循两条规则:

当输入被分解成标记时,如果 行的最终标记是

  • 标识符
  • 整数、浮点数、虚数、符文或字符串文字
  • 关键字 break、continue、fallthrough 或 return 之一
  • 运算符和分隔符之一 ++、--、)、] 或 }

为了让复杂的语句占据一行, 在结束的 ")" 或 "}" 之前可以省略分号。

为了反映惯用用法,本文档中的代码示例省略 使用这些规则的分号。

据我从他们的谈话中了解到,他们想摆脱格式讨论,并通过 gofmt 的伟大来扩展这个想法

【讨论】:

  • 如果形式语法使用分号,那么为什么要让人们选择省略它们呢?在我看来,他们牺牲了清晰度来安抚那些不能被一键打扰的人......
  • 我认为 Go 对“如何格式化源代码”的相当严格的方法是该语言的一大优势。它使深入研究其他人的代码,尤其是库变得非常容易和愉快。当我必须用其他语言做同样的事情时,例如javascript,通常感觉就像必须学习语言的“新”子集。作者的目的是解决由 10.000 名编码人员(即谷歌规模编程)工作的 x billon LOC 代码库产生的问题。通常,问题更多在于坚持一种格式化方式,而不是找到“正确的方式”。
【解决方案4】:

因为 google 的人不喜欢 allman 风格。 但是支持allman风格很容易,forkGo(by @diyism) 只在golang编译器中添加了12行代码。

试试 forkGo: https://github.com/forkgo-org/go

forkGo 支持这样的 allman 风格:

package main
import
(
    "fmt"
)


func main()
{
    if false
    {   fmt.Println("jack")
        fmt.Println("forkgo")
    } else
    {   fmt/
           .Println("hello")
        fmt.Println("forkgo")
    }
}

【讨论】:

    【解决方案5】:

    ..."他首先要使用大括号(即,使大括号排列在同一列上的语句块的范围很容易识别),"...

    同意 - 如果您想对齐大括号以区分块,这非常困难

    【讨论】:

      猜你喜欢
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      相关资源
      最近更新 更多