翔云

Just try, don't shy. 最新文章请点击
随笔 - 294, 文章 - 0, 评论 - 27, 阅读 - 49万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

golang channel 的使用

Posted on   翔云123456  阅读(339)  评论(0编辑  收藏  举报

本文对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/

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示