【发布时间】:2016-02-06 01:03:38
【问题描述】:
我有一些代码接收 protobuf 消息,这些消息基本上在几个地方重复,所以我想把它放到一个库中。问题是每组代码使用的确切 protobuf 消息不同。
编辑:而且我没有重组它们的灵活性。
我不完全确定这是否可以在没有重复代码的情况下解决,但我确实尝试过(如下)。我做错了什么,还是这不是不可能的事情? (注意:这是精简的代码,在实际代码中,对象有很多额外的字段)
Example.proto:
package testmsg;
enum RepStatus {
DONE_OK = 0;
DONE_ERROR = 1;
}
message ReqHeader {
optional int64 user_id = 1;
}
message RespHeader {
optional RepStatus status = 1;
optional string error_msg = 2;
}
message PostReq {
optional ReqHeader header = 1;
optional bytes post_data = 2;
}
message PostResp {
optional RespHeader header = 1;
}
message StatusReq {
optional ReqHeader header = 1;
optional string id = 2;
}
message StatusRep {
optional RespHeader header = 1;
optional string status = 2;
}
mini-service/service.go:
package miniservice
import "reflect"
import "github.com/golang/protobuf/proto"
import "testmsg"
type MiniService struct {
name string
reqType reflect.Type
repType reflect.Type
}
func NewService(name string, reqPort int, reqType proto.Message, repType proto.Message) *MiniService {
ms := new(MiniService)
ms.name = name
ms.reqType = reflect.TypeOf(reqType)
ms.repType = reflect.TypeOf(repType)
return ms
}
func (ms *MiniService) Handler(msgs []string) (string) {
resp := reflect.New(ms.repType.Elem())
msg := msgs[0]
req := reflect.New(ms.reqType.Elem())
err := proto.Unmarshal([]byte(msg), req)
//add some error handling, or just get set _
resp.Header = &testmsg.RespHeader{}
//Call handler function that is unique per service
//the signature will be something like:
//handleRequest(reqType, respType) & called like:
//handleRequest(req, resp)
resp.Header.Status = testmsg.RepStatus_DONE_OK.Enum()
respMsg, _ := proto.Marshal(resp)
return string(respMsg)
}
testservice.go:
package main
import "github.com/golang/protobuf/proto"
import "testmsg"
import "mylibs/mini-service"
func main() {
//fake out a zmq message
req := &testmsg.PostReq{}
req.Header = &testmsg.ReqHeader{}
req.Header.MessageId = proto.Int64(10)
reqMsg, _ := proto.Marshal(req)
reqMsgs := []string{string(reqMsg)}
ms := miniservice.NewService("tester", 5555, testmsg.PostReq, testmsg.PostResp)
//What will be called when receiving a zmq request
resp := ms.Handler(reqMsgs)
log.Info(resp)
}
当我尝试编译时,我收到如下错误:
resp.Header undefined (type reflect.Value has no field or method Header)
cannot use resp (type reflect.Value) as type proto.Message in argument to proto.Marshal:
reflect.Value does not implement proto.Message (missing ProtoMessage method)
这很有意义,因为 resp 没有连接到 ms.respType。
【问题讨论】:
标签: templates generics go metaprogramming