golang-plugin模式代码热更之-可恶的protobuf重名注册panic问题

  如果你在使用golang的plugin模式进行代码热更新时会发现protobuf编译生成的xxxxx.pb.go文件中会生成2个init方法。这2个init方法会向"github.com/golang/protobuf/proto"包的全局变量进行注册,原本这种注册在常规的golang程序中是没有任何问题的,因为一个package的init方法只会调用一次。但是在使用plugin模式时,如果xxxxx.pb.go文件是在plugin插件代码中,那么每次新插件加载的时候都会调用对应包的init方法,并且因为需要热更新plugin,所以就会进行多次调用了。因为在"github.com/golang/protobuf/proto"包中多次进行注册同名的类型名会触发panic,因此起初我要解决的问题是如何可以避免这个panic? 我们先看看触发panic的代码片段:[crayon-6745d847cd7ea821558988/]  每次golang宿主程序加载新的插件hotswap_myplugin.so(该插件包含error.pb.go代码文件)都会调用上面的init方法中的RegisterEnum进行枚举类型的注册触发panic。为了解决这个问题我想到2个思路:  1. 每次新的插件变更error.pb.go中的变量的命名  2. 去除init方法中的注册代码  根据实际应用场景的分析,第一种方法不太适用,因为每次都变更error.pb.go的命名的话意味着插件中的其他代码引用error.pb.go中的类型或者变量的代码都需要全部修改,这对于需要经常热更的代码场景来说显得比较麻烦,一个原因是类似error.pb.go的文件会非常多,每次所有的proto文件都需要修改,另一个原因是所有引用代码也需要全盘修改。这个方式显得非常鸡肋,因为大多数时候如果我只想修改一行代码去修复某个bug,却要花费大量的时间代价去重命名proto定义文件去避免重名注册panic。  那么如此只好使用第二种方式了,第二种方式是希望能够不要执行init方法中的注册方法那么就不会触发重复注册panic了。好家伙,这意思是要从源头解决问题了,no...
Read More