這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go中的控制語句較精簡,僅有if、for、select和switch。但使用時均比較靈活
if
在Go中條件陳述式*if*中如果條件部分的計算結果為**true**時將執行語句塊,否則則執行else語句塊(如果存在else時),此邏輯和其他語言中的if一樣,但是在Go中還是有一些不同之處。
- if條件運算式不能使用花括弧**()**包含
- if語句程式碼片段必須使用**{}**,並且左括弧必須和if在同一行
- if條件運算式的前面可以包含初始化語句,支援平行賦值,但不支援多個指派陳述式
賦值+條件判斷
if a, b := 21, 3; a > b { fmt.Println("a>b ? true")}
在if條件運算式前面聲明的的變數只能在if-else語句塊中使用。
if a, b := 21, 31; a > b { fmt.Println("a>b ? true")}else { fmt.Println(a,b) //Ok}fmt.Println(a,b) //error: undefined a ,undefined b
還需要注意的是如果在if-else 中包含return 時,編譯器無法解析出else中的retrun,導致方法缺少return ,目前1.1版本已支援該方式。
func getName(id int) string { if id == 1 { return "YourName" }else { return "MyName" } //panic("")}
此代碼編譯不通過,錯誤資訊:function ends without a return statement,這是在設計Go時故意這樣的,也可以說是一個Bug(可參見:https://code.google.com/p/go/issues/detail?id=65),這是一種編碼風格,即在if語句塊中去做return處理,而else中不處理,而是繼續執行if-else後面的代碼,這樣能減少一個代碼縮排,不需要在瞭解代碼時去記住else語句塊的處理。當然如果想必須這樣寫,也可以進行特殊處理,在函數的末行添加語句**panic("")**
在if中可以包含初始化語句,這是非常實用的。例如在檔案處理,取字典項時需要判斷是否執行操作成功,只有在成功時才能繼續處理,這樣就可以通過if-else處理。
if err := file.Chmod(0664); err != nil { log.Print(err) return err}if v,err :=myMap[key];err != nil { log.Print(err) return err}else { //do something with v}
for
在Go中其他迴圈遍曆的控制語句,唯有for。而for同樣也是比較靈活的,for有三種形式。
- 普通用法 for init; condition;post {}
- while for condition {}
- 死迴圈 for {}
由於Go沒有逗號運算式,而++和--是語句而不是運算式,如果想在for中執行多個變數,需要使用平行賦值
for i, j := 1, 10; i < j; i,j=i+1,j+1 { //死迴圈 fmt.Println(i)}
而不能寫成
for i, j := 1, 10; i < j; i++,j++ { fmt.Println(i)}
for的condition在每執行一次迴圈體時便會執行一次,因此在實際開發過程中需要注意不要讓condition中計算簡單而不是複雜。
for i,j :=0,len(str); i<j ; i++ { fmt.Println(str[i])}
而不要寫成(這僅是一個示範而已)
for i=0; i< len(str); i++ { fmt.Println(str[i])}
另外for是遍曆string,array,slice,map,chanel的方式,而使用保留字rang則能靈活的處理。rang是迭代器,能根據不同的內容,返回不同的東西。
- for index,char := range string {}
- for index,value := range array {}
- for index,value := range slice {}
- for key,value := range map {}
需要注意的是for+rang遍曆string時得到的是位元組索引位置和UTF-8格式rune類型資料(int32)。
for pos, value := range "Go在中國" { fmt.Printf("character '%c' type is %T value is %v, and start at byte position %d \n", value,value,value, pos) str :=string(value) //convert rune to string fmt.Printf("string(%v)=>%s \n",value,str)}---------OutPut------------ 一個漢字佔三個位元組character 'G' type is int32 value is 71, and start at byte position 0 string(71)=>G character 'o' type is int32 value is 111, and start at byte position 1 string(111)=>o character '在' type is int32 value is 22312, and start at byte position 2 string(22312)=>在 character '中' type is int32 value is 20013, and start at byte position 5 string(20013)=>中 character '國' type is int32 value is 22269, and start at byte position 8 string(22269)=>國
break和continue
另外在迴圈中使用break和continue,break用於退出迴圈,continue用於終止本次迴圈體的執行繼續執行下一個迴圈。
sum := 0for { if sum > 10 { break } sum += 2}fmt.Println(sum) // sum=12
break也可退出指定的迴圈體
sum := 0myforLable: for { for i := 0; i < 10; i++ { if sum > 200 { break myforLable //將退出迴圈體for{} } sum += i } } fmt.Println(sum)
switch
switch是最靈活的一種控制語句,運算式可以不是常量或者字串,也可以沒有運算式,如果沒有運算式則如同if-else-else。
一般用法:和其他語言的Switch基本一樣,不同的不需要在每個Case中添加Break,而是隱藏了Break,當然你可以顯示加入break
switch ch { case '0': cl = "Int" case '1': cl = "Int" case 'A': cl = "ABC" break //可以添加 case 'a': cl = "ABC" default: cl = "Other Char" }
此段代碼可以可寫成(fallthrough表示繼續執行下面的Case而不是退出Switch)
switch ch {case '0': fallthrough //必須是最後一個語句case '1': cl = "Int"case 'A': case 'a': fallthrough cl = "ABC" //errordefault: cl = "Other Char"}
如果多個匹配結果所對應的程式碼片段一樣,則可以在一個case中並列出所有的匹配項
switch ch { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': cl = "Int" case 'A', 'B', 'C', 'D', 'a', 'b', 'c', 'd', 'e': cl = "ABC" default: cl = "Other Char"}
同樣switch可以沒有運算式,在 Case 中使用布林運算式,這樣形如 if-else
switch { case '0' <= ch && ch <= '9': cl = "Int" case ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'): cl = "ABC" default: cl = "Other Char"}
下面是Switch寫的一個樣本(無實際意義):
func Compare(a, b interface{}) (int, error) { aT := reflect.TypeOf(a) bT := reflect.TypeOf(b) if aT != bT { return -2, errors.New("進行比較的資料類型不一致") } switch av := a.(type) { default: return -2, errors.New("該類型資料比較沒有實現") case string: switch bv := b.(type) { case string: return ByteCompare(av, bv), nil } case int: switch bv := b.(type) { case int: return NumCompare(av, bv), nil } } return -2, nil}
select
還有另一個控制語句select,在討論chan 時再來學習
上一篇(數組和切片)