V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Siril
V2EX  ›  程序员

golang 单对多 channel ?

  •  
  •   Siril · 2017-01-31 14:29:49 +08:00 · 6320 次点击
    这是一个创建于 2851 天前的主题,其中的信息可能已经有所发展或是发生改变。
    golang 这里有人用吗

    居然没有内置这种功能。。。
    想到个办法,在此抛砖引玉

    刚试着弄了个,思路是制造一个链式的结构,
    链上的每个元素对应一个 goroutine ,这个 goroutine
    读取上一个节点发过来的数据扔到输出 channel 上,并转发给下一个。
    输出 channel 阻塞就退出自己。(所以发送必须比接收慢)
    而且链上有多少个节点,相当于多少容量的 buffer ,
    无法确认消息送达到全部 channel

    type chaincast struct {
    v interface{} //message payload.
    out chan interface{} //message output channel
    spawn chan<- chaincast //send to this channel to spawn goroutine for chain element.
    next chan chaincast //channel for passing message to next
    prev chan chaincast //channel for receiving message from prev
    }
    代码在这,可能有大 bug :
    https://play.golang.org/p/6D9wZ9Qnp8
    15 条回复    2017-03-20 17:53:37 +08:00
    SuperFashi
        1
    SuperFashi  
       2017-01-31 14:55:01 +08:00 via Android
    用途?
    Valyrian
        2
    Valyrian  
       2017-01-31 14:58:43 +08:00
    以前用 golang 作业写过类似的东西。。
    Siril
        3
    Siril  
    OP
       2017-01-31 15:06:16 +08:00
    @SuperFashi
    就是一个 goroutine 从网络或者标准输入或其他地方得到了一个消息,
    需要将其发给一组 goroutine 。

    这场景应该是比较常见吧。
    ovear
        4
    ovear  
       2017-01-31 15:09:53 +08:00
    这个不是直接封装 chan 就好了么
    一个分发 chan ,一个 slice ,多个处理 chan
    分发 chan 里面直接循环往 slice 的 chan 塞东西就好了。。有啥问题么?
    jarlyyn
        5
    jarlyyn  
       2017-01-31 15:14:02 +08:00 via Android
    没看懂用途
    jarlyyn
        6
    jarlyyn  
       2017-01-31 15:16:20 +08:00 via Android
    @Siril

    按你 3 楼的描述,觉得起个 go 专门塞 Chan

    然后多个 go 取 Chan 的问题么
    buckethead1
        7
    buckethead1  
       2017-01-31 15:30:30 +08:00
    就是 pub/sub 么...
    Siril
        8
    Siril  
    OP
       2017-01-31 15:49:45 +08:00
    @jarlyyn

    对,就是一个 go routine 负责从外部读取一些东西塞 chan ,
    其他一组 go routine 需要取 chan ,
    这组 go routine 随时有新增和退出。

    如果不用 mutex 。。。
    lecher
        9
    lecher  
       2017-01-31 15:53:17 +08:00 via Android
    生产者和消费者模型,七牛的公开技术文档经常提到这个设计模式在内部项目的应用场景。
    wweir
        10
    wweir  
       2017-01-31 15:59:47 +08:00 via Android
    chan 的 close 信号是广播的
    Siril
        11
    Siril  
    OP
       2017-01-31 17:15:11 +08:00
    @ovear 我似乎理解你说的意思,就是元素为 chan 的 slice 。
    一开始就是这么弄的, 然后发现 2 个问题:
    新开的 goroutine 需要获取一个 chan 用来收消息;
    一个收消息的 goroutine 可能随时退出,然后这个 slice 大小只增不减。
    ovear
        12
    ovear  
       2017-01-31 17:22:53 +08:00
    @Siril 这个问题很好解决啊
    在分发线程检测是否有无效 chan ,有的话从 slice 中删除就好了

    的确是典型的生产者 消费者问题,我一时没想起来
    SuperFashi
        13
    SuperFashi  
       2017-01-31 18:16:12 +08:00
    @Siril 啊,看懂了
    但是这种东西最好的解决办法不就是 for 一遍塞 chan 吗……
    你可以把 slice 做成线程安全,每次线程退出自己删自己就好了
    nareix
        14
    nareix  
       2017-02-01 09:37:59 +08:00
    sync.Cond
    codehz
        15
    codehz  
       2017-03-20 17:53:37 +08:00
    我记得反射就可以了。。。性能应该会比用链式结构的好吧
    `reflect.Select`可以接收一个数组
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   977 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:45 · PVG 04:45 · LAX 12:45 · JFK 15:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.