英文:
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
我来为你翻译一下:
我想强调几点:
- Go语言受到许多语言的启发,不仅仅是C语言。
- C语言:语句和表达式语法
- Pascal语言:声明语法
- Modula 2、Oberon 2语言:包
- CSP、Occam、Newsqueak、Limbo、Alef语言:并发性
- BCPL语言:分号规则
- Smalltalk语言:方法
- Newsqueak语言:<-、:=
- APL语言:iota
还有其他语言的影响。
-
从什么时候开始,
foreach
和range
变成了C语言风格的语法? -
第三点,不要将"For"语句与
for
子句和range
子句混淆。请阅读规范。
在Go语言中,你也可以这样做:
for i := 0; i < len(numbers); i++
但是一旦你理解了range
子句,它就更加强大,而且它并不是奇怪的语法。我建议你阅读规范并看一些例子。
此外,阅读Go的常见问题解答和Pike关于声明语法的博客。常见问题解答应该能回答很多类似的问题。
英文:
Few points that I'd like to highlight:
- 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
- From when
foreach
andrange
become C-style syntax? - Third, don't confuse "For" statements with
for
clause andrange
clause. Read the spec.
In Go, you can do this is as well:
for i := 0; i < 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.
- Also, it's Go and not GoLang (Read). Always prefer the former over the latter.
- 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有fmt
和io
包,尽管它们有一些重叠。例如,fmt.Fprint
允许你写入任何io.Writer
,fmt.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
是大写的,因为以大写字母开头的任何函数都是“公共”函数。这样可以节省在每个地方输入public
或pub
的时间。
英文:
import "io"
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 > 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)
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论