[Go] 利用channel造成管道溝通循環內外

這個要解決的問題是,好比若是有一個大循環,取自一個大的文件,要進行邏輯處理,那麼這個邏輯的代碼要放在循環每一行的循環體裏面,這樣有可能會出現一個for循環的邏輯嵌套,一層又一層,相似俄羅斯套娃.若是放在外面那麼就須要把大循環的每一行數據存到一個數組或者切片裏面,這樣會佔很大的內存數組

那麼就能夠使用這種技巧來既能解決循環嵌套,又能解決不存在佔用大內存的數據緩存

建立一個channel,開啓一個goroutine,在groutine裏面進行for循環遍歷,把每一行的數據發送到channel中
在主groutine裏面,讀取channel,由於接收者老是比發送者先執行,那麼這個地方就會阻塞等待那一個數據到來
這樣就造成這樣一個良性的同步操做,雖然是在不一樣的groutine裏面執行的,可是老是同步執行的,而且解決了循環嵌套的問題app

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,後循環外才執行,這個在不少的案例裏都有使用spa

yields := make(chan int, 6)
循環內 1
循環內 2
循環內 3
循環內 4
循環內 5
循環內 6
循環外: 1
循環外: 2
循環外: 3
循環外: 4
循環外: 5
循環外: 6

好比說這樣的代碼:code

    mailboxes := make(chan *imap.MailboxInfo, 20)
    go func() {
        imapClient.List("", "*", mailboxes)
    }()
    //列取郵件夾
    for m := range mailboxes {
        mailDirs = append(mailDirs, m.Name)
    }

這個很像是PHP中的yield的做用,溝通函數內外blog

相關文章
相關標籤/搜索