Go語言可能會遇到的坑

最近在用go開發項目的過程當中忽然發現一個坑,尤爲是對於其它傳統語言轉來的人來講一不注意就掉坑裏了,話很少說,咱看代碼:golang

 

1//writeToCSV
2func writeESDateToCSV(totalValues chan []string) {
3    f, err := os.Create("t_data_from_es.csv")
4    defer f.Close()
5    if err != nil {
6        panic(err)
7    }
8
9    w := csv.NewWriter(f)
10    w.Write(columns)
11
12    for {
13        select {
14        case row := <- totalValues:
15            //fmt.Printf("Write Count:%d log:%s\n",i, row)
16            w.Write(row)
17        case <- isSendEnd:
18            if len(totalValues) == 0 {
19                fmt.Println("------------------Write End-----------------")
20                break
21            }
22        }
23    }
24
25    w.Flush()
26    fmt.Println("-------------------------處理完畢-------------------------")
27    isWriteEnd <- true
28}ide

 

當數據發送完畢,即isSendEnd不阻塞,且totalValues裏沒數據時,跳出for循環,這裏用了break。可是調試的時候發現,程序阻塞在了14行,即兩個channel都阻塞了。而後才驚覺這裏break不是這麼玩,而後寫了個測試方法測試一下:oop

 

package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                break
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }

    fmt.Println("outside the for: ")
}測試

 

運行輸出以下結果,break now以後仍是會繼續無限循環,不會跳出for循環,只是跳出了一次select調試

 

inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
break now
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: code

 

 

若要break出來,這裏須要加一個標籤,使用goto, 或者break 到具體的位置。開發

 

 

解決方法一:string

 

使用golang中break的特性,在外層for加一個標籤:it

 

package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0

    endLoop:
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                break endLoop
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }

    fmt.Println("outside the for: ")
}io

 

 

解決方法二: 

 

使用goto直接跳出循環:

 

package main

import (
    "time"
    "fmt"
)

func main() {
    i := 0
    for {
        select {
        case <-time.After(time.Second * time.Duration(2)):
            i++
            if i == 5{
                fmt.Println("break now")
                goto endLoop
            }
            fmt.Println("inside the select: ")
        }
        fmt.Println("inside the for: ")
    }
    endLoop:
    fmt.Println("outside the for: ")
}

 

兩程序運行輸出以下:

 

inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
inside the select: 
inside the for: 
break now
outside the for: 

Process finished with exit code 0

 

 

綜上能夠得出:go語言的switch-case和select-case都是不須要break的,可是加上break也只是跳出本次switch或select,並不會跳出for循環。

 

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索