多行语句中自动添加 ; 符号

Go 会在当行尾的元素属于以下元素时,自动添加 ; 符号:

因此下列多行语句都是非法的:

  1. i := 1 + 2 + 3 + 4 // 会自动添加 ;
  2. + 5 // error
  3. i, j, k := 1, 2 // 会自动添加 ;
  4. , 3 // error
  5. if i > 0 && j > 0 // 会自动添加 ;
  6. && k > 0 { // error
  7. }

参考 Go Spec:https://go.dev/ref/spec#Semicolons

没有 ?: 三目运算符

Go 中没有 ?: 三目运算符,需要使用 if {...} else {...} 语句来替换。因为 Go 的设计者认为 ?: 运算符经常被用于创建难以理解的表达式,而 if {...} else {...} 语句虽然冗余但易于理解。

参考 Go FAQ:https://go.dev/doc/faq#Does_Go_have_a_ternary_form

以 goroutine 来运行闭包

下面这段代码期望输出是 a b c(不过可能是乱序的),但实际输出的却是 c c c。这是因为在 for 循环的每次迭代中,都会使用相同的变量 v 实例(&v 值是相同的),并且 goroutine 中每个闭包都共享了这个变量 v。当闭包在运行时通过 fmt.Printf 打印变量 v 的值时,变量 v 可能在 goroutine 启动之后就被修改了。可以使用 go vet 命令来检测这类潜在的问题。

  1. done := make(chan bool)
  2. values := []string{"a", "b", "c"}
  3. for _, v := range values {
  4. go func() {
  5. fmt.Printf("%v ", v)
  6. done <- true
  7. }()
  8. }
  9. for range values {
  10. <-done
  11. }

为了避免上述问题,可以在 goroutine 启动时把变量 v 的当前值绑定到各个闭包上。例如把变量 v 作为参数传递给闭包。

  1. for _, v := range values {
  2. go func(u string) {
  3. fmt.Printf("%v ", u)
  4. done <- true
  5. }(v)
  6. }

参考 Go FAQ:https://go.dev/doc/faq#closures_and_goroutines