Tendermint之go-wire

在基于Tendermint增加一个已有rpc接口参数的时候,是考虑增加接口还是扩张接口,这两者都比较麻烦

增加接口的话扩展性不强

扩展接口的话也比较麻烦,一整套接口都得改,而且后续扩展性不强

想着在数据的前面加一个byte代表类型,接收方去获取第一个byte判断类型后续为数据,但是这样有点赤裸裸的workaround的感觉了,看到已有的go-wire有类似效果,就是这个想法上的包装,所以看看怎么使用的

go-wire是什么

查了下没查到,看起来是Tendermint自己做的?

它的作用是传输数据的时候按照定义的格式encode为二进制传输,接收端接收到数据后按照定义的格式decode二进制位结构化数据。

初始化

使用之前需要先注册,以Tendermint的mempool为例

var _ = wire.RegisterInterface(
	struct{ MempoolMessage }{},
	wire.ConcreteType{&TxMessage{}, msgTypeTx},
        wire.ConcreteType{&TxMessage{}, msgTypeTx},
)
为了方便演示,我将第3行复制了一遍

需要调用wire的RegisterInterface

func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo {
	it := GetTypeFromStructDeclaration(o)
	if it.Kind() != reflect.Interface {
		cmn.PanicSanity("RegisterInterface expects an interface")
	}
	toType := make(map[byte]reflect.Type, 0)
	toByte := make(map[reflect.Type]byte, 0)
	for _, ctype := range ctypes {
		crt := reflect.TypeOf(ctype.O)
		typeByte := ctype.Byte
		if typeByte == 0x00 {
			cmn.PanicSanity(cmn.Fmt("Byte of 0x00 is reserved for nil (%v)", ctype))
		}
		if toType[typeByte] != nil {
			cmn.PanicSanity(cmn.Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte]))
		}
		toType[typeByte] = crt
		toByte[crt] = typeByte
	}
	typeInfo := &TypeInfo{
		Type: it,
		IsRegisteredInterface: true,
		ByteToType:            toType,
		TypeToByte:            toByte,
	}
	typeInfos[it] = typeInfo
	return typeInfo
}

1 获取o的struct type,其实就是获取到了类型MempoolMessage

2 for循环ctypes参数,也就是剩下的其余的参数

拿到ctype的类型crt和值typeByte(该值不能为0,0默认为nil),然后分别加入到map toType和toByte,

组织为TypeInfo返回,同时加入到最后加入到map typesInfos中

所以初始化的目的就是把定义的type和value加入到map typesInfos中, type为key。typeInfos中的元素就是解析好的value,有两个map保存value结构type和value

写入数据

写入数据的时候调用接口BinaryBytes。以上述为例子,写入的参数为

struct{ MempoolMessage }{msg},(其中msg为&TxMessage{Tx: tx})就是下面的参数o

func BinaryBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteBinary(o, w, n, err)
	if *err != nil {
		cmn.PanicSanity(*err)
	}
	return w.Bytes()
}

接着看WriteBinary

func WriteBinary(o interface{}, w io.Writer, n *int, err *error) {
	rv := reflect.ValueOf(o)
	rt := reflect.TypeOf(o)
	writeReflectBinary(rv, rt, Options{}, w, n, err)
}

这里要获取参数的value和type,分别为msg何MempoolMessage

接下来的writeReflectBinary就是把结构化的数据转成byte数组最终传递出去了

unc writeReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, w io.Writer, n *int, err *error) {

	// Get typeInfo
	typeInfo := GetTypeInfo(rt)

	if rt.Kind() == reflect.Interface {
		if rv.IsNil() {
			WriteByte(0x00, w, n, err)
			return
		}
		crv := rv.Elem()  // concrete reflection value
		crt := crv.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值