golang channel 的使用

来源:互联网 发布:太行发动机知乎 编辑:程序博客网 时间:2024/09/21 09:21

本文对channel使用中的几个疑惑,以例子的形式加以说明。

普通channel

缺省情况下,发送和接收会一直阻塞着,直到另一方准备好.
例如:

package mainimport (        "fmt"        "time")var ch1 chan boolfunc 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.exewrite one ...read one ....read one ....write one ...read one ....write one ...read one ....write one ...从执行结果看,reader卡住,直到writer sleep后就位,才继续执行。反之,让reader先睡眠,writer也会卡住,直到reader sleep后就位。<div class="se-preview-section-delimiter"></div>##带buffer的channel带buffer的channel可以减少阻塞,对一些需要只保持有限个执行过程的情景很有用。例1:<div class="se-preview-section-delimiter"></div>

// 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:<div class="se-preview-section-delimiter"></div>

// 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/