1. 程式人生 > >golang channel 的使用

golang channel 的使用

參考 mark log port 準備 lan mar case .com

本文對channel使用中的幾個疑惑,以例子的形式加以說明。

普通channel

缺省情況下,發送和接收會一直阻塞著,直到另一方準備好.
例如:

package main

import (

        "fmt"
        "time"

)

var ch1 chan bool

func main(){


        ch1 = make(chan bool)

        go reader()
        go writer()

        select {
        }

}

func writer() {

        time.Sleep(10*time.Second)
        for {

                ch1 <- true
                fmt.Println("write one ...")
        }

}



func reader() {

        for {
                select {
                case <-ch1:
                        fmt.Println("read one ....")
                }

                time.Sleep(2*time.Second)
        }
}

output:

$ ./chan1.exe
write one ...
read one ....
read one ....
write one ...
read one ....
write one ...
read one ....
write one ...

從執行結果看,reader卡住,直到writer sleep後就位,才繼續執行。反之,讓reader先睡眠,writer也會卡住,直到reader sleep後就位。

帶buffer的channel

帶buffer的channel可以減少阻塞,對一些需要只保持有限個執行過程的情景很有用。

例1:

// reader wait, until writer begin to write.
package main

import (

        "fmt"
        "time"

)

var ch1 chan bool

func main(){


        ch1 = make(chan bool, 1)

        go reader()
        go writer()

        select {
        }

}

func writer() {

        time.Sleep(10*time.Second)
        for {

                ch1 <- true
                fmt.Println("write one ...")
        }

}



func reader() {

        for {
                select {
                case <-ch1:
                        fmt.Println("read one ....")
                }

                time.Sleep(2*time.Second)
        }
}

這種情景中,先讓writer睡眠,reader此時卡住,直到writer就位,也就是說,帶buffer,如果沒有數據寫入,reader也是卡住的。

例2:

// writer write one, then wait
package main

import (

        "fmt"
        "time"

)

var ch1 chan bool

func main(){


        ch1 = make(chan bool, 1)

        go reader()
        go writer()

        select {
        }

}

func writer() {

        for {

                ch1 <- true
                fmt.Println("write one ...")
        }

}



func reader() {

        time.Sleep(10*time.Second)
        for {
                select {
                case <-ch1:
                        fmt.Println("read one ....")
                }

                time.Sleep(2*time.Second)
        }
}

如果先讓reader睡眠,writer直接向channel寫,可以看到writer可以寫入一個數據,然後卡住,直到reader就位,才可以繼續寫。
也就是說,帶一個buffer的channel,可以在reader就位前首先寫入一個數據。

參考

http://colobu.com/2016/04/14/Golang-Channels/

golang channel 的使用