golang 流程控制

Go語言的流程控制主要分爲三大類:

1. 條件判斷
2. 循環控制
3. 無條件跳轉

條件判斷

Go語言的條件判斷由if ... else if ... else 語句實現,條件表達式值必須是布爾類型,可省略圓括號,但是花括號不能省略且左花括號不能另起一行,比如:

if 7%2 == 0 {
    fmt.Println("7 is even")
} else {
    fmt.Println("7 is odd")
}    
if 8%4 == 0 {   //可以沒有else只有if語句
    fmt.Println("8 is divisible by 4")
}

Go語言比較特別的是在條件判讀語句中支持初始化語句,允許定義局部變量,但是這個變量的作用域僅限於該條件邏輯塊內,比如:

if num := 9; num < 0 {
    fmt.Println(num, "is negative")
} else if num < 10 {
    fmt.Println(num, "has 1 digit")
} else {
    fmt.Println(num, "has multiple digits")
}

最典型的應用就是字典的查找:

if v, ok := map1[key1]; ok{
    ...
}

優化建議:

  1. 對於那些過於複雜的組合條件判斷,建議獨立出來封裝成函數,將流程控制和實現細節分離,使你的代碼更加模塊化,提高可讀性.

  2. 有些時需要寫很多的if-else實現一些複雜的邏輯處理,這時代碼看上去就很羅嗦很冗長,而且也不易於以後的維護,用switch...case來很好的解決這個問題.


switch...case

switch與if類似,也用於選擇執行,執行的過程從上至下順序匹配各個case,基本用法如下:

switch sExpr {    
    case expr1:
        some instructions    
    case expr2:
        some other instructions
    case expr3:
        some other instructions
    default:
        other code
}

switch中的表達式可以不是常量或字符串,甚至可以沒有表達式,若沒有表達式則匹配true, 如同if-else if-else,與 其它編程語言的switch用法基本相同,不同的是在每個case中隱藏了break,不過也可以顯示加入break。 當case匹配成功後,處理當前case的處理邏輯,正常情況下,處理完成後就跳出整個switch,但這不是絕對的, 可以使用fallthrough強迫程序執行後面的case; 如果沒有任何case匹配成功,則執行default邏輯,比如:

免寫break:

{
    i := 2
    switch i {              //將i 與case條件匹配
        case 1:
            fmt.Println("one")  //break沒有實際意義,直接跳出switch
        case 2:
            fmt.Println("two")  
        case 3:
            fmt.Println("three")
    }
}

多表達式判斷:

{    
    switch time.Now().Weekday() {
        case time.Saturday, time.Sunday: //在同一個case中可以寫多個表達式,它們之間是邏輯或的關係
            fmt.Println("it's the weekend")
        default:
            fmt.Println("it's a weekday")
    }
}

無表達式:

{
    t := time.Now()   
    switch {            //沒有表達式,相當於if-else
        case t.Hour() < 12:
            fmt.Println("it's before noon")    
        default:
            fmt.Println("it's after noon")
    }
}

fallthrough:

{
    i := 2
    switch i {    
        case 1:
            fmt.Println("one")    
        case 2:
            fmt.Println("two")
            fallthrough    //使用fallthrough強迫程序執行後面的case
        case 3:
            fmt.Println("three")
    }
}

循環控制

for是Go語言中僅有的一種循環語句,下面是常見的三種用法:

for j := 7; j <= 9; j++ { //典型的用法 initial/condition/after
    fmt.Println(j)
}

i := 1
for i <= 3 {            //類似while(i <= 3){} 或for ; i<=3 ;;{}
    fmt.Println(i)
    i = i + 1
}

for {    //類似while(true){} 或for true {}
    fmt.Println("loop")   
    ...     
    break
}

PS:初始化語句只會被執行一次,並且初始化表達式支持函數調用或定義局部變量

在日常開發中for經常與range搭配,for...range被用來遍歷字符串、數組、切片、字典和通道等,返回索引和鍵值數據,比如:

{    for i, c := range "go" {            //range string
        fmt.Println(i, c)
    }

    nums := []int{2, 3, 4}    
    for i, num := range nums {          //range array/slice
        fmt.Println(i, ":", num)
    }

    kvs := map[string]string{"a": "apple", "b": "banana"}    
    for k, v := range kvs {         //range map
        fmt.Printf("%s -> %s\n", k, v)
    }

    chs := make(chan int,10)    //range channel
    chs <- 1
    chs <- 2
    close(chs)                                                                                                                                                                                                     
    for v := range chs {
        fmt.Println(v)
    }
}

簡單歸納如下:

data typefirst valuesecond value
stringindexs[index]
array/sliceindexv[index]
mapkeyvalue
channelelement


無條件跳轉

Go語言有三種跳轉類型,分別是 continue, break, goto

continue:僅用於for循環內部 ,終止本次循環,立即進入下一輪循環
break:用於for循環, switch,select語句,終止整個語句塊的執行
goto:定點跳轉,但不能跳轉到其他函數或內層代碼塊內

看下面的例子:

func over(){
    over:   //label over defined and not used
    println("call over")
}
func main(){
    rand.Seed(time.Now().UnixNano())    
    for {
        loop:
        x := rand.Intn(100)     //獲取一個100以內的隨機數
        if x % 2 == 0{            
            continue        //終止本次循環,立即進入下一輪循環
        }        
        if x > 50{           
            break           //終止整個語句塊的執行
        }        
        println(x)
    }    
    goto over       //label over not defined
    goto loop       //goto loop jumps into block starting}

goto 的習慣用法:

{
    f, err := os.Open("/tmp/dat")    
    if err != nil{
        ....
         goto exit
    }
    ...
    n1, err := f.Read(b1)
    if err != nil{ 
        goto end
    }
    ...

end:    
    println("clear resource and exit")
    f.close()
exit:    
    return
}

借鑑: 雨痕<GO學習筆記>

討論學習: 675020908

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章