Technical reasons behind Go's strange syntax

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

Technical reasons behind Go's strange syntax

问题

我最近开始学习Go语言,对于它为什么有一种奇怪的“非传统”语法,与其他语言(如C、C++、C#、Java)不同,感到相当困惑。

例如,在Go中,像这样的代码:

package main

import "fmt"

func sum(a int, b int) int {
    return a + b
}

func main() {
    numbers := [4]int{1, 2, 3, 4}

    for _, n := range numbers {
        result := sum(n, 2)
        fmt.Println(result)
    }
}

但是,在其他一些语言中,可以这样写:

package main

import "io"

int sum(int a, int b) {
    return a + b
}

void main() {
    int numbers[4] = {1, 2, 3, 4}

    foreach (n in range(numbers)) {
        result = sum(n, 2)
        io.print(result)
    }
}

所以我的问题是,这种语法背后是否有任何技术原因,还是只是团队的个人偏好?特别是Go语言的开发团队使用“C语言”来编写Go,这意味着使用C风格的语法更有意义,对吗?

英文:

I recently started learning to Go, and I am quite confused as to why it has a strange "non-traditional" syntax unlike other languages (C, C++, C#, JAVA)

For example, a code like this in Go:

package main

import "fmt"

func sum(a int, b int) int {
	return a + b
}

func main() {
	numbers := [4] int {1, 2, 3, 4}

	for _,n := range numbers {
		result := sum(n, 2)
    	fmt.Println(result)
	}
}

But, could be written something like in some languages:

package main

import "io"

int sum(int a, int b) {
    return a + b
}

void main() {
    int numbers[4] = {1, 2, 3, 4}
    
    foreach (n in range(numbers)) {
        result = sum(n, 2)
        io.print(result)
    }
}

So my question is, is there any technical reason behind this syntax, or is it just a personal preference of the team? Especially that the team behind Go used "C Language" to write Go, which means it would've made much more sense to type it in C-Style syntax ?

答案1

得分: 4

我来为你翻译一下:

我想强调几点:

  1. Go语言受到许多语言的启发,不仅仅是C语言。
  • C语言:语句和表达式语法
  • Pascal语言:声明语法
  • Modula 2、Oberon 2语言:包
  • CSP、Occam、Newsqueak、Limbo、Alef语言:并发性
  • BCPL语言:分号规则
  • Smalltalk语言:方法
  • Newsqueak语言:<-、:=
  • APL语言:iota
    还有其他语言的影响。
  1. 从什么时候开始,foreachrange变成了C语言风格的语法?

  2. 第三点,不要将"For"语句与for子句和range子句混淆。请阅读规范
    在Go语言中,你也可以这样做:

for i := 0; i < len(numbers); i++

但是一旦你理解了range子句,它就更加强大,而且它并不是奇怪的语法。我建议你阅读规范并看一些例子。

  1. 另外,它是Go而不是GoLang(阅读)。始终优先选择前者。

  2. 尝试一下Go之旅。其中解释了一些概念。

此外,阅读Go的常见问题解答Pike关于声明语法的博客。常见问题解答应该能回答很多类似的问题。

英文:

Few points that I'd like to highlight:

  1. Go is inspired by many languages and not just C.
  • C: statement and expression syntax
  • Pascal: declaration syntax
  • Modula 2, Oberon 2: packages
  • CSP, Occam, Newsqueak, Limbo, Alef: concurrency
  • BCPL: the semicolon rule
  • Smalltalk: methods
  • Newsqueak: <-, :=
  • APL: iota
  • There are more
  1. From when foreach and range become C-style syntax?
  2. Third, don't confuse "For" statements with for clause and range clause. Read the spec.
    In Go, you can do this is as well:
for i := 0; i &lt; len(numbers); i++

But range clause is much more powerful once you understand it and yes it is not strange syntax. I'd suggest to read the spec and see a few examples.

  1. Also, it's Go and not GoLang (Read). Always prefer the former over the latter.
  2. Try the Go Tour. Some concepts are explained well.

Also, read Go's FAQ and Pike's blog on declaration syntax. The FAQ should answer many such queries.

答案2

得分: -1

import "io"

Go有fmtio包,尽管它们有一些重叠。例如,fmt.Fprint允许你写入任何io.Writerfmt.Fscan允许你从任何io.Reader读取。

类似地,你可以使用io.Copy(os.Stdout, something)向控制台写入,使用io.Copy(something, os.Stdin)从控制台读取。

func sum(a int, b int) (n int)

我记得通过将func放在前面,可以使词法解析更快。此外,Go函数可以具有命名返回值:

func sum(a int, b int) (n int)

我不确定你如何使用其他语法实现这一点。

numbers := [4]int{1, 2, 3, 4}

Go语法允许你省略类型,这在C中是不允许的。

for _, n := range numbers {
    println(n)
}

Go没有while关键字,因为较少的关键字可以使词法解析更快。相反,你可以使用不同的for调用方式:

var n int
for {
    if n > 9 {
        break
    }
    println(n)
    n++
}

var n int
for n < 9 {
    println(n)
    n++
}

for n := 0; n < 9; n++ {
    println(n)
}

for range numbers {
    println("hello")
}

for index := range numbers {
    println(index)
}

for index, value := range numbers {
    println(index, value)
}

对于这个:

result = sum(n, 2)

Go有两种不同的变量赋值语法:

result := 1
result = 2

第一种是声明,第二种是对已声明变量的赋值。

fmt.Println(result)

fmt.Println是大写的,因为以大写字母开头的任何函数都是“公共”函数。这样可以节省在每个地方输入publicpub的时间。

英文:
import &quot;io&quot;

Go has fmt and io packages, although they do have some overlap. For example, fmt.Fprint lets you write to any io.Writer, and fmt.Fscan lets you read from any io.Reader.

Similarly you can write to console with io.Copy(os.Stdout, something), and read from console with io.Copy(something, os.Stdin).

int sum(int a, int b) {

I think I read that by having func first, it makes lexical parsing much faster. Also Go function can have named return values:

func sum(a int, b int) (n int)

I am not sure how you'd do that with the other syntax.

int numbers[4] = {1, 2, 3, 4}

Go syntax allows you to omit the type, which you can't do with C.

foreach (n in range(numbers))

Go doesn't have a while keyword, for the reason that less keywords again makes for faster lexical parsing. Instead you have different for invocations:

var n int
for {
   if n &gt; 9 {
      break
   }
   println(n)
   n++
}

var n int
for n &lt; 9 {
   println(n)
   n++
}

for n := 0; n &lt; 9; n++ {
   println(n)
}

for range numbers {
   println(&quot;hello&quot;)
}

for index := range numbers {
   println(index)
}

for index, value := range numbers {
   println(index, value)
}

For this:

result = sum(n, 2)

Go has two different syntax for variable assignment:

result := 1
result = 2

First is a declaration, second is assigning to an already declared variable.

io.print(result)

fmt.Println is uppercase, because any function that starts with an uppercase letter is a "public" function. This saves on typing public or pub everywhere.

huangapple
  • 本文由 发表于 2021年6月18日 11:02:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/68028786.html
匿名

发表评论

匿名网友

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

确定