這個要解決的問題是,比如如果有一個大迴圈,取自一個大的文件,要進行邏輯處理,那麼這個邏輯的代碼要放在迴圈每一行的迴圈體裡面,這樣有可能會出現一個for迴圈的邏輯嵌套,一層又一層,類似俄羅斯套娃.如果放在外面那麼就需要把大迴圈的每一行數據存到一個數組或者切片裡面,這樣會占很大的記憶體 那麼就可以使用這種 ...
這個要解決的問題是,比如如果有一個大迴圈,取自一個大的文件,要進行邏輯處理,那麼這個邏輯的代碼要放在迴圈每一行的迴圈體裡面,這樣有可能會出現一個for迴圈的邏輯嵌套,一層又一層,類似俄羅斯套娃.如果放在外面那麼就需要把大迴圈的每一行數據存到一個數組或者切片裡面,這樣會占很大的記憶體
那麼就可以使用這種技巧來既能解決迴圈嵌套,又能解決不存在占用大記憶體的數據
創建一個channel,開啟一個goroutine,在groutine裡面進行for迴圈遍歷,把每一行的數據發送到channel中
在主groutine裡面,讀取channel,因為接收者總是比發送者先執行,那麼這個地方就會阻塞等待那一個數據到來
這樣就形成這樣一個良性的同步操作,雖然是在不同的groutine裡面執行的,但是總是同步執行的,並且解決了迴圈嵌套的問題
package main import "fmt" import "time" func main() { arr := []int{1, 2, 3, 4, 5, 6} yields := make(chan int) go func() { for _, i := range arr { //每次這裡先列印,然後跳到迴圈外 fmt.Println("迴圈內", i) yields <- i //這是防止執行太快看不到效果 time.Sleep(time.Second) } close(yields) }() for i := range yields { fmt.Println("迴圈外:", i) } }
就是這樣的效果
迴圈內 1 迴圈外: 1 迴圈內 2 迴圈外: 2 迴圈內 3 迴圈外: 3 迴圈內 4 迴圈外: 4 迴圈內 5 迴圈外: 5 迴圈內 6 迴圈外: 6
如果那個channel是個有緩存的channel,就會先把緩存數量的全都塞進channel,後迴圈外才執行,這個在很多的案例里都有使用
yields := make(chan int, 6) 迴圈內 1 迴圈內 2 迴圈內 3 迴圈內 4 迴圈內 5 迴圈內 6 迴圈外: 1 迴圈外: 2 迴圈外: 3 迴圈外: 4 迴圈外: 5 迴圈外: 6
比如說這樣的代碼:
mailboxes := make(chan *imap.MailboxInfo, 20) go func() { imapClient.List("", "*", mailboxes) }() //列取郵件夾 for m := range mailboxes { mailDirs = append(mailDirs, m.Name) }
這個很像是PHP中的yield的作用,溝通函數內外