Go基礎-010 流程控制

1.概述

代碼的執(zhí)行順序,有 3 大類,為:

  • 順序,從上到下依次執(zhí)行,基礎流程(核心流程)
  • 循環(huán),某段代碼重復執(zhí)行。
  • 分支,選擇性執(zhí)行某段代碼。

2.流程圖回顧

使用如下的典型圖例,描述流程節(jié)點:

  • 橢圓,表示開始和結束:


  • 矩形,表示某個具體的進程步驟:


  • 菱形,表示條件判斷:


3. 分支if

1) 語法
  • 語法 1,只有 if 語句
// 語法 1,條件成立,執(zhí)行語句塊內(nèi)容
if condition {
  // 語句塊 
}
  • 語法 2,if + else
// 語法 2,條件成立,執(zhí)行 if 語句塊,否則執(zhí)行 else 語句塊 
if condition {
  // if 語句塊 
} else {
  // else 語句塊 
}
  • 語法 3,else if
// 語法 3,條件 1 成立,執(zhí)行語句塊 1 然后結束,若條件 1 不成立,繼 續(xù)判斷條件 2,若成立執(zhí)行語句塊 2 然后結束。直到全部條件判斷完畢。
condition1, condition2, conditionN := true, true, true 
if condition1 {
/  / 語句塊 1
} else if condition2 {
  // 語句塊 2
} else if conditionN {
  // 語句塊 N 
}
  • 語法 4,else if else
// 語法 4,與語法 3 一致,多一個 else 語句塊,當全部條件不滿足時,執(zhí)行 else 語句塊 
if condition1 {
  // 語句塊 1
} else if condition2 {
  // 語句塊 2
} else if conditionN {
  // 語句塊 N 
} else {
  // else 語句塊
 }
  • 條件表達式為布爾表達式
    條件表達式一定是可以返回布爾值的表達式。不能直接判斷 0,”” 這種非布爾類型數(shù)
    據(jù),沒有自動向布爾值轉(zhuǎn)換的過程,下面的語法是不對的:
if 0 { 
  // non-bool 0 (type int) used as if condition
  fmt.Println("if statement block") 
}

  • 支持條件初始化語句
    在 if 后,支持先完成條件初始化,再去完成條件表達式的語法,結構為:

if 條件初始化語句;條件表達式 {
}

if condition := 10>8; condition { 
  fmt.Println("使用條件初始化語句")
  fmt.Println("條件成立") 
}

注意:以上結構中,條件的是否成立,僅僅與條件表達式相關,與條件初始化語句無關。

if c:=10<8;true{ 
    fmt.Println(c)
    fmt.Println("使用條件初始化語句")
    fmt.Println("條件成立")
}

// false 
// 使用條件初始化語句 
// 條件成立

注意:使用條件初始化的意思,主要是為了將判斷條件變量的作用域(有效區(qū)域)限定在 if 語句 范圍內(nèi)(縮小變量有效作用域策略), condition2,在 if 外無效。

if condition2 := 10>8; condition2 { 
 fmt.Println("使用條件初始化語句")
 fmt.Println("條件成立")
 fmt.Println(condition2)
}
fmt.Println(condition2) //undefined: condition2

4.分支 switch

1) if 和 switch 的差異?

if,條件分支,利用條件表達式確定條件是否成立。
switch,狀態(tài)分支,利用狀態(tài)值確定分支條件。

代碼演示:

    // score >= 80 就是條件
    score := 98
    if score >= 90 {
        fmt.Println("A")
    } else if score >= 80 {
        fmt.Println("B")
    } else if score >=60 {
        fmt.Println("C")
    } else {
        fmt.Println("呵呵")
    }

      // int,string,bool,就是特定的狀態(tài)!
    switch d := 10; d {
    case 9 :
        fmt.Println(9)
    case 10 :
        fmt.Println(10)
    case 11 :
        fmt.Println(11)
    default:
        fmt.Println("default")
    }
2) 語法,switch case default
value := 4 
switch value { 
default:
  fmt.Println("six") 
case 1:
  fmt.Println("one") 
case 2:
  fmt.Println("two")
//...
case 3, 4, 5: // value == 3 || value == 4 || value == 5
  fmt.Println("three, four, five") }

執(zhí)行流程是,判斷 switch 表達式的值與 case 給定的狀態(tài)是否相等,相等則執(zhí)行對應的語句 塊,然后 switch 結束。
注意,多個狀態(tài)值,可以在一個 case 中描述。
注意,若沒有任何 case 匹配,則會執(zhí)行 default 分支。前提是存在 default 分支。(default 分
支是可選的)。default 的位置無關。

在 switch 表達式中,同樣支持初始化表達式。 支持:
switch 初始化表達式; switch 表達式 {
}
目的是將條件分支值變量的有效作用域控制在 switch 語句的范圍內(nèi),避免全局污染!
代碼演示:

switch value := 4; value { 
default:
  fmt.Println("six") 
case 1:
  fmt.Println("one") 
case 2:
  fmt.Println("two") 
//...
case 3, 4, 5:  // value == 3 || value == 4 || value == 5
  fmt.Println("three, four, five") 
}

fmt.Println(value) //undefined: value

格外注意的是,switch 的 switch 表達式是也可以省略的。(if 的條件表達式是不能省略的。) 省略后,case 應該使用條件語句完成分支判斷,不能再使用狀態(tài)值了,因為沒有值可以用
于判定了。

switch value := 4; { 
default:
  fmt.Println(value)
  fmt.Println("six") 
case value == 1:
  fmt.Println("one") 
case value == 2:
  fmt.Println("two")
case value == 3 || value == 4 || value == 5: 
  fmt.Println("three, four, five")
}
3) fallthrough,穿越到下個 case 塊

go 的 switch case 在滿足了一個 case 后,執(zhí)行對應的語句塊,之后 swtich 直接結束。
與很多其他語言不通的是,很多其他語句的 swtich 當 case 滿足后會依次執(zhí)行余下的 全部語句塊。
為了在語法上與其他語言類似,go 提供了 fallthrough 語句,用于在 case 語句塊間穿越。 當 case 語句塊的最后的語句為 fallthrought 時,會執(zhí)行下一個 case 語句塊:

switch value := 2; value { 
default:
  fmt.Println("six") 
case 1:
  fmt.Println("one") 
case 2:
  fmt.Println("two") 
  fallthrough // 
//...
case 3, 4, 5: // value == 3 || value == 4 || value == 5
  fmt.Println("three, four, five") 
  //fallthrough // 最后一個語句塊中不能存在 fallthrough
}

// 輸出 two  
// three, four, five

注意:
fallthrough 只能是語句塊的最后一條語句。
而且最后一個語句塊中不能存在 fallthrough。
若執(zhí)行的語句塊不存在 fallthrough,會停止穿越!

4) switch interface.(type) 結構,type switch

該結構可以完成類型檢測,執(zhí)行對應的代碼。

// 類型檢測
var x interface{} 
//x = 42
x = "hank"
//x = false
//
switch d := x.(type) { 
case int:
  fmt.Println(d, d+42) 
case string:
  fmt.Println(d, d + " GoLang")
  //fallthrough //cannot fallthrough in type switch
case bool:
  fmt.Println(d, !d) 
}

該結構也是 swtich 的語法。
特殊性在于: 不支持 falltrhrough。

5. 循環(huán) for

1) 概述

基于循環(huán)條件,重復執(zhí)行代碼塊的結構。 流程圖上,通常是一個閉合的環(huán)。
語法上使用 for 完成循環(huán)結構。(go 語言中沒有 while 結構循環(huán))

2) 基本語法
for 條件初始化語句;條件表達式;條件更新語句{
  //循環(huán)體
}

for i:=0; i<10; i++ {
   fmt.Println(i)
}

for 存在三個循環(huán)條件部分,初始化,條件判斷,條件變化。

若 循環(huán)體執(zhí)行了 N 次,那么:

  • 條件初始化執(zhí)行 1 次。
  • 條件判斷執(zhí)行 N+1 次。
  • 條件變化執(zhí)行 N 次。
    可見,應該將條件數(shù)據(jù)放在初始化中完成,避免重復執(zhí)行,例如,當使用 i 作為索引, 遍歷數(shù)組或切片的時候,語法為:
arr := [...]int{42, 1024, 365, 2048, 1, 36, 88, 66} 
for i, l := 0, len(arr); i<l; i++ {
  fmt.Println(i, arr[i]) 
}
// 不建議的語法
for i := 0; i<len(arr); i++ {
  fmt.Println(i, arr[i]) 
}
3) 條件循環(huán)語法(其他語言的 while 語法)
for 條件表達式 {
}
result, n := 0, 0 
for result <= 100 {
  n ++
  result += n 
}
fmt.Println(result)

條件的數(shù)據(jù)依賴于外部數(shù)據(jù)完成。
通常循環(huán)體內(nèi)部,要完成循環(huán)條件的更新。

4) 無限循環(huán)語法
for {
}
i := 0
for { // for true {
  fmt.Println(i) i ++
  if i >= 10 {
    break // 強制 for 終止 
  }
}

不需要 循環(huán)條件,表示條件永遠為 true。 意味著,循環(huán)體會無限次數(shù)的循環(huán)執(zhí)行下去。
通常,需要配合循環(huán)體內(nèi)部的條件變化以及在循環(huán)體內(nèi)部強制終止來實現(xiàn)。上面的 break
結構。
該結構通常用于實現(xiàn)守護進程。需要一直運行的程序。

6. 循環(huán)遍歷,for range

適用于遍歷:array,slice,map 復合結構。
語法一致:

for i, v := range data { 
}
for i := range data { 
}
for _, v := range data {
}

7. 注意,語句塊的左大括號,與語句標簽在一行

for ;; {
if ; {
swtich ; {
for := range {

\\ 不能是:
for ;; 
{
if ; 
{
switch ; 
{
// 包括函數(shù)的大括號,也需要與函數(shù)聲明在一行。
func funcName() {

8. goto label

label: 語句標簽。類似于路標,用于標識代碼位置。
使用 goto 語句可以跳轉(zhuǎn)到特定的 label 位置。

演示,例如在處理錯誤時:

// 錯誤處理
// 可能的錯誤有很多種,逐一檢測。
// 一旦檢測到任意的錯誤,則立即處理錯誤,不再檢測后續(xù)的錯誤,邏輯如
下:
if error1 {
   goto errorLabel
}
if error2 {
   goto errorLabel
}
if error3 { //標簽跳轉(zhuǎn)
   goto errorLabel
}
errorLabel: // 標簽定義 
  fmt.Println("error processing")

上面的語法中,涉及到了:

  • 定義標簽: 為標簽設置特定的名字,滿足標識符定義即可。
  • 使用標簽: 完成。 跳轉(zhuǎn)標簽:使用 goto 完成跳轉(zhuǎn)。

注意: 跳轉(zhuǎn) goto,不是任意跳轉(zhuǎn)。跳轉(zhuǎn)的目標不是任何位置都可達到,例如: 不能跨函數(shù)跳轉(zhuǎn)。
不能跳轉(zhuǎn)到內(nèi)部的語句塊中。

總結下來:標識符必須可見,才可以 goto 成功。
標識符可見的語法: 語句塊嵌套的可見性。內(nèi)層可以看見外層,但是外層看不到內(nèi)層。
不同的語句塊也不可以跳轉(zhuǎn)。

func main() {
  goto labelName
  // 內(nèi)層可以看見外層,但是外層看不到內(nèi)層。
  for i:=0;i<10;i++ {
    labelName:  // XXX 不可
      fmt.Println()
  }
}
// 不同的語句塊也不可以跳轉(zhuǎn)。
func F() {
   labelName:  // XXX 不可
      fmt.Println()
}

9. break,強行終止循環(huán)執(zhí)行

break 用于循環(huán)內(nèi)部,當執(zhí)行到 break 時,會終止 break 所在的循環(huán)的執(zhí)行。
代碼演示

for i:=0; i<10; i++ { 
  if i == 6 {
    break
  }
  fmt.Println(i) 
}

以上結果,6 及后續(xù)數(shù)字沒有輸出。執(zhí)行到了 break,會立即終止。

10.continue,強行終止本次循環(huán)體執(zhí)行,循環(huán)繼續(xù)

continue,僅僅終止本次循環(huán)體執(zhí)行。但是 for 的整體循環(huán)并沒有結束,會繼續(xù)修改循
環(huán)條件,執(zhí)行下一次循環(huán)體。
代碼演示:

for i:=0; i<10; i++ { 
  if i == 6 {
    continue
  }
  fmt.Println(i) 
}

以上的結果,沒有 6 的輸出。continue 之后的代碼,不會繼續(xù)執(zhí)行,而是指向下一次 i== 7 的循環(huán)體。

11.break 或 continue 多重循環(huán)

當循環(huán)語句出現(xiàn)嵌套時,若需要在內(nèi)部循環(huán)體中,直接終止外部的循環(huán)執(zhí)行,則需要配
合 標簽 語法完成終止。 演示:

outerLabel:
for i:=0; i<3; i++ {
  for j:=0; j<3; j++ {
      if i + j > 2{
        break outerLabel
     }
     fmt.Println(i, j) 
  }
}

此時,break outerLabel, 會導致 outerLabel 對應的 for 全部終止! 否則,break,僅僅會終止 所在的 for j 的執(zhí)行,而不會終止 for i 的執(zhí)行。

12.switch 中的 break 一定要使用標簽

for 中使用 switch 結構判斷執(zhí)行 break,需要使用標簽語法。

代碼演示:

forLabel:
  for i:=0; i<10; i++ {
   switch i {
   case 6:
     break forLabel
   }
   // if i == 6 {
   // break
   // } 
  fmt.Println(i)
}

若不使用標簽語法,switch 中的 break 不會終止循環(huán)。
原因,switch 中的 break,是終止 switch 的作用。在實現(xiàn) switch 時,被視為循環(huán)結構。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內(nèi)容

  • Swift 提供了類似 C 語言的流程控制結構,包括可以多次執(zhí)行任務的for和while循環(huán),基于特定條件選擇執(zhí)行...
    窮人家的孩紙閱讀 715評論 1 1
  • [The Swift Programming Language 中文版]本頁包含內(nèi)容: Swift提供了多種流程控...
    風林山火閱讀 577評論 0 0
  • Swift提供了多種控制流聲明。包括while循環(huán)來多次執(zhí)行一個任務;if,guard和switch聲明來根據(jù)確定...
    BoomLee閱讀 1,976評論 0 3
  • 控制流 [TOC] Swift提供了多種流程控制結構,包括可以多次執(zhí)行任務的while循環(huán),基于特定條件選擇執(zhí)行不...
    伍哥___閱讀 518評論 0 0
  • 本章將會介紹 控制流For-In 循環(huán)While 循環(huán)If 條件語句Switch 語句控制轉(zhuǎn)移語句 continu...
    寒橋閱讀 736評論 0 0