【GoLang】GoLang for 中有多個循環變量怎么處理?


代碼示例:

    sum := 0
    for i, j := 0, 0; i <= 5 && j <= 5; i, j = i+1, j-1 {
        t.Log("i: ", i)
        t.Log("j: ", j)
        sum += i + j
    }
    t.Log("sum: ", sum)

 

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 := 0
for {
    if sum > 10 {
        break
    }
    sum += 2
}
fmt.Println(sum) // sum=12

break也可退出指定的循環體

    sum := 0
myforLable:
    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"    //error
default:
    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 時再來學習

 

 

參考資料:

http://www.cnblogs.com/howDo/archive/2013/06/01/GoLang-Control.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM