Generic Programming with Protobuf?

polaris · · 495 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m working with a bunch of PB messages that I don&#39;t have much control over, so messages are like <code>PermissionsReq</code>, <code>AccountReq</code>, <code>DataReq</code>. The pb messages all share a header field, but the other fields are all different (i.e. an <code>AccountReq</code> has fields like <code>add_account</code>, <code>remove_account</code>, <code>get_account_info</code>, etc.). The header itself has fields that include account ids, status, </p> <p>I have a few services that each work with their own message type, and they all do a lot of the same thing, especially when it comes to the header. They also do things like send off events to other services. There is a lot of repeated code between all these services, with the only difference being the protobuf message type - and I want to put this into a shared lib. Is there a way I can work around this? I posted on SO with some very stripped down code: <a href="http://stackoverflow.com/questions/35236079/go-reflect-for-metaprogramming-templates">http://stackoverflow.com/questions/35236079/go-reflect-for-metaprogramming-templates</a></p> <hr/>**评论:**<br/><br/>callcifer: <pre><p>Not sure if I fully understand your question, but can&#39;t you just add a specific &#34;handler&#34; for each message type and move common functionality into a common handler?</p> <p>For example, in my codebase all messages have a &#34;type&#34; field:</p> <pre><code>enum MessageTypes { PING_MSG = 1; } message PingMessage { required MessageTypes type = 1; optional string whatever = 2; } </code></pre> <p>On the Go side, I have a map of handlers for each message type. Every handler embeds <code>baseHandler</code> where I collect common functionality. <code>GenericMessageHandler</code> is just an interface with a <code>Handle</code> method.</p> <pre><code>func (h *RequestHandler) init() { h.handlers = make(map[mpm.MessageTypes]GenericMessageHandler, 10) h.handlers[mpm.MessageTypes_PING_MSG] = handlers.PingHandler{&amp;handlers.baseHandler{}} } </code></pre> <p>which I later use with:</p> <pre><code>handler, ok := h.handlers[*msg.Type] if ok { response := handler.Handle(msg) } </code></pre> <p>Would something like that work for you?</p></pre>sciclaw: <pre><p>I couldn&#39;t get it working for me. I unmarshalled when the <code>PostReq</code> message was received, then passed the message into a function with common code. When I passed it I tried passing the message both as a <code>proto.Message</code> object and using custom interface <code>messageWithHeader</code>. I was able to get the common code working that way. But when I wanted to add my custom <code>PostReq</code> code, I got stuck. Once the <code>PostReq</code> was converted to the more generic types, I couldn&#39;t figure out how to convert it back to pass to the handler.</p> <p>I tried moving the code to call the specific <code>PostReq</code> handler outside the shared code, but I ended up moving most of the shared code over as well in order to set up all the required variables, so it wasn&#39;t really helping.</p> <p>I found a solution that I&#39;m not completely unhappy with. I put the shared code in a file I called <code>base.tmp.go</code> using <code>{{RequestProto}}</code> and <code>{{ResponseProto}}</code> as placeholders. I then add a go generate line to each file that will use a handler to run a script that replaces the strings with what&#39;s needed. The meat of the script (which I put in the bin dir) is:</p> <pre><code>SERVICE_DIR=$(dirname &#34;$0&#34;)/../src/mygolibs/test-service mkdir -p ${SERVICE_DIR}/${1}/ GEN_FILE=${SERVICE_DIR}/${1}/${1}_service.go cp ${SERVICE_DIR}/base.tmpl.go ${GEN_FILE} sed -i&#34;&#34; -e &#34;s/{{RequestProto}}/${2}/g&#34; ${GEN_FILE} sed -i&#34;&#34; -e &#34;s/{{ResponseProto}}/${3}/g&#34; ${GEN_FILE} </code></pre> <p>Then I add this in my file before importing:</p> <pre><code>//go:generate build_service post PostRequest PostResponse import &#34;mygolibs/test-service/post&#34; </code></pre></pre>

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

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