<p>I'm working with a bunch of PB messages that I don'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't you just add a specific "handler" for each message type and move common functionality into a common handler?</p>
<p>For example, in my codebase all messages have a "type" 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{&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'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'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't really helping.</p>
<p>I found a solution that I'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's needed. The meat of the script (which I put in the bin dir) is:</p>
<pre><code>SERVICE_DIR=$(dirname "$0")/../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"" -e "s/{{RequestProto}}/${2}/g" ${GEN_FILE}
sed -i"" -e "s/{{ResponseProto}}/${3}/g" ${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 "mygolibs/test-service/post"
</code></pre></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传