以太坊golang-event 简单使用

aside section ._1OhGeD · · 965 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近阅读到miner部分代码,看到里面的事件订阅提起了兴趣就研究了一下,以后做项目也许会用到。
以太坊提供了两种event事件模型,typeMux和feed,两者在使用上会有一点区别,前者可以订阅任意类型的消息,而后者由于subscribe的入参为chan,故类型在第一次使用时就确定,也就是一个feed只能对应一个类型的chan。前者如果订阅者始终没有读取chan消息,那么整个流程会阻塞,影响其他订阅者正常读取消息,性能低下,故以太坊中只有极少地方使用typeMux,主要是feed。而feed比较灵活,如果chan设置了缓冲,那么就可以异步,没有缓冲则效果和typeMux一样。

package main

import (
    "fmt"
    "github.com/ethereum/go-ethereum/event"
    "time"
)

type test struct {
    data int
}

type test1 struct {
    data int
}

func main() {
    //subMux()
    feed()
    select {}
}

//typeMux   同步事件模型
func subMux() {
    var mux event.TypeMux

    go func() {
        ch := mux.Subscribe(test{})
        for v := range ch.Chan() {
            fmt.Println("test:", v.Data.(test))
        }
    }()

    go func() {
        sub := mux.Subscribe(test1{})
    loop:
        time.Sleep(time.Second * 7) //模拟test1读取管道阻塞,test等待
        v := <-sub.Chan()
        fmt.Println("test1:", v.Data.(test1))
        goto loop
    }()

    go func() {
        for i := 0; i < 10000; i++ {
            time.Sleep(time.Second)
            _ = mux.Post(test1{i})
            _ = mux.Post(test{i})
        }
    }()
}

//可异步事件模型,feed管理的管道类型固定。
func feed() {
    var fee event.Feed
    var scope event.SubscriptionScope //统一管理sub,统一关闭通道及取消订阅

    go func() {
        ch := make(chan test, 100)
        sub := fee.Subscribe(ch)
        scope.Track(sub)
        for {
            select {
            case v := <-ch:
                fmt.Println("ch test1:", v)
            case <-sub.Err():
                fmt.Println("sub closed")
                return
            }
        }
    }()

    go func() {
        ch := make(chan test, 100) //添加带缓冲的管道,异步模式
        sub := fee.Subscribe(ch)
        scope.Track(sub)
    loop:
        time.Sleep(time.Second * 5) //模拟读取管道阻塞
        select {
        case v := <-ch:
            fmt.Println("ch test1:", v)
        case <-sub.Err():
            fmt.Println("sub1 closed")
            return
        }
        goto loop
    }()

    go func() {
        for i := 0; i < 1000; i++ {
            time.Sleep(time.Second)
            fee.Send(test{i})
        }
    }()

    go func() {
        time.Sleep(time.Second * 10)
        scope.Close()
    }()
}


附别人的源码分析,http://lessisbetter.site/2018/10/18/ethereum-code-event-framework/,讲得很好。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:aside section ._1OhGeD

查看原文:以太坊golang-event 简单使用

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

965 次点击  
加入收藏 微博
上一篇:string
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传