![](https://raw.githubusercontent.com/studygolang/gctt-images/master/simple-statement/1_HO_nLfJ1LDrODqso68AcwA.jpeg) [https://en.wikipedia.org/wiki/Kiss_(band)](https://en.wikipedia.org/wiki/Kiss_%28band%29)在 Golang [規範](https://golang.org/ref/spec)中有一個術語:簡單語句(simple statement),可能在整個文檔中不經常使用,但語言的文法只允許在幾個重要的地方使用這些語句。這篇短文的目的就是介紹這些簡單語句和可以使用它們的地方。![](https://raw.githubusercontent.com/studygolang/gctt-images/master/simple-statement/1_Sh2PTmHloYTNWptEXj4FrA.jpeg)<center>Photography: Ursula Coyote/Netflix</center>在規範中,它由 SimpleStmt 產生式定義(使用 [EBNF](https://golang.org/ref/spec#Notation)):```SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .```下面我們將介紹 6 種簡單語句## 1. 空白語句顯然,在簡單語句中,空白語句就是什麼都不做。## 2. 自增或自減語句```gox++ // 語義上等價於賦值x + = 1x-- // x -= 1```在 Go 中,在運算式運算元後用 “--” 或 “++” 構成的不是運算式(譯註:Go 中 "--" 或 "++" 不是運算式,而是語句),因此您不會在 `.go` 源檔案中看到讓人類似下面糾結的組合:```gofoo = bar++ + 10```儘管這是一個語句,但是作為簡單語句是需要用在有意義的地方並且不會在不應該的地方引入不必要的**負擔**(通過使代碼難以閱讀和難以維護)。> **在 Golang 中沒有首碼版本,即在操作對象之前放置 “--” 或 “++”。**## 3. 發送語句詞法標記 “<-” 表示通過 channel 發送值。它不返回任何值,因此不需要表達它。## 4. 運算式語句某些運算式可以放入語句中。> **塊是由大括弧括起來的一系列語句,例如,運算式語句在如下情況下完全有效。**允許的選項如下:- 函數調用(除了一些內建函數,例如 append,cap,complex,imag,len,make,new,real,[unsafe](https://golang.org/pkg/unsafe/).Alignof,unsafe.Offsetof 和unsafe.SizeOf)- 方法調用- 接收操作符```gofunc (s S) m() { fmt.Printf("Hi %s\n", s.name)}func f(n int) { fmt.Printf("f says %d\n", n)}func main() { f(1) s := S{"Michał"} s.m() c := make(chan int) go func() { c <- 1 }() <-c numbers := []int{1, 2, 3} len(numbers) // error: len(numbers) 被執行了但是並未使用}```## 5. 指派陳述式大家應該都熟悉一些最基本的賦值形式。首先必須聲明變數,右邊的運算式必須可以[賦值](https://studygolang.com/articles/12381)給一個變數:```govar population int64population = 8000000 // 賦值var city, country string// 兩個單值運算式賦值給兩個變數city, country = "New York", "USA"```當把一個以上的值分配給變數列表時,有兩種形式。第一種形式,一個運算式返回多個值,例如函數調用:```gof := func() (int64, string) { return 2000000, "Paris"}var population int64var city stringpopulation, city = f()```第二種形式是右側包含有許多運算式, 但每一個是單值的:```gopopulation, city = 13000000, "Tokyo"```這兩種形式不可以被混淆:```gof := func() (int64, string) { return 4000000, "Sydney"}var population int64var city, country stringpopulation, city, country = f(), "Australia"```上面這行代碼在編譯的時候會拋出 "multiple-value f() in single-value context"。賦值操作是一個由 “=” 符號組成的構造,等號前面是一個二元運算子:- 加 (+)- 減 (-)- 位元運算 或 (|)- 位元運算 異或 (^)- 乘 (*)- 除 (/)- 取餘 (%)- 位元運算 左移 右移 (<< 和 >>)- 位元運算 與 (&)- 位清除 (&^)`a op= b`(例如 a += b)在語義上等同於 `a = a op b`,但 a 只被計算一次。賦值操作也是有效指派陳述式.## 6. 簡單變數聲明下面是常規變數語句的縮寫,它們需要初始化。此外,未明確指定的類型是從初始化語句中使用的類型推斷出來的:```gos := S{}a := [...]int{1,2,3}one, two := f(), g()```現在我們應該很清楚是什麼構成了一組有效簡單語句。但是它們用在什麼地方呢?## if 語句簡單語句可以選擇性地放在條件運算式之前。它經常用於聲明變數(使用短變數語句),然後在運算式中使用:```gogen := func() int8 { return 10}if num := gen(); num > 5 { fmt.Printf("%d is greater than 5\n", num)}```## for 語句for 語句中的初始化或聲明變數只能是簡單語句。常見的用法是將短變數聲明作為初始聲明以及賦值操作或自增/自減語句:```gofor i := 0; i < 10; i += 1 { fmt.Println(i)}```當然了,也沒有東西阻止程式員在這個地方使用其他的簡單語句。## switch 語句與 if 語句類似,可以在 [switch 運算式](https://golang.org/ref/spec#Expression_switches)之前將可選的簡單語句放入運算式中:```goswitch aux := 2; letter {case 'a': fmt.Println(aux)case 'b': fmt.Println(aux << 1)case 'c': fmt.Println(aux << 2)default: fmt.Println("no match")}```或者在 [type switch](https://golang.org/ref/spec#Type_switches) 的守衛前面:```gotype I interface { f(num int8) int8}type T1 struct{}func (t T1) f(num int8) int8 { return 1}type T2 struct{}func (t T2) f(num int8) int8 { return 2}...var i I = T1{}switch aux := 10; val := i.(type) {case nil: fmt.Printf("nil %T %d\n", val, aux)case T1: fmt.Printf("T1 %T %d\n", val, aux)case T2: fmt.Printf("T2 %T %d\n", val, aux)}```它的輸出為:```T1 main.T1 10```
via: https://medium.com/golangspec/simple-statement-notion-in-go-b8afddfc7916
作者:Michał Łowicki 譯者:yousanflics 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
360 次點擊 ∙ 1 贊