我正在编写一个 rpc 调用流程。当我使用tcp读写时,我发现另一个嵌套结构问题。我创建了一个请求和响应对象,其中包含一个traceId和struct请求对象或返回对象结构,但是当我在服务器上写回客户端的响应对象时,我无法在客户端gob反序列化上得到正确的回复对象实体可以只获取traceId。我想问这是什么原因。代码如下在这里输入图片描述
// Server
for {
// Read data from connection
data, err := readData(conn)
if err != nil {
if err.Error() == "EOF" {
return
} else {
log.Printf("Server readData error: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
} else if len(data) == 0 {
continue
}
// Decode the data from client request
var req Request
edcode, err := GetEdcode()
if err != nil {
log.Printf("Server encode error: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
err = edcode.Decode(data, &req)
if err != nil {
log.Printf("Server decode error: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
// Get the service from the registerd service map
methodStr := strings.Split(req.MethodName, ".")
if len(methodStr) != 2 {
log.Printf("Server methodStr length invalid: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
service := server.ServiceMap[methodStr[0]][methodStr[1]]
// Construct the request args
argv, err := req.MakeArgs(edcode, *service)
// Construct reply data
reply := reflect.New(service.ReplyType.Elem())
// Call the method related
function := service.Method.Func
out := function.Call([]reflect.Value{reflect.New(server.ServerType.Elem()), argv, reply})
if out[0].Interface() != nil {
log.Printf("Server out result length invalid: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
// Construct response data
response := NewResponse(req.TraceId, reply.Elem().Interface())
// We should register the matching type related to the GOB encoding to prevent the encoding error
codeErr := response.RegisterGobRespType()
if codeErr != nil {
log.Printf("Server response.RegisterGobRespType eror : %v, remoteAddr:%v", codeErr.Error(), conn.RemoteAddr().String())
return
}
// Encode the reply data to send to the client
//replyData, err := edcode.Encode(reply.Elem().Interface())
replyData, err := edcode.Encode(response)
if err != nil {
log.Printf("Server replayData encode error: %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return
}
// Write data to connection
_, err = writeData(conn, replyData)
if err != nil {
return
}
}
Client
// Receive and read the encoding response data from client
replyData, err := readData(conn)
if err != nil {
log.Printf("Client writeData eror : %v, remoteAddr:%v", err.Error(), conn.RemoteAddr().String())
return err
}
var response etnet.Response;
// Decode data and assign it to reply variable
//var response etnet.Response, response reply is always nil and I check the write value in server it is correct
edcode.Decode(replyData, &response)
type Request struct {
TraceId string
MethodName string
Args interface{}
}
type Response struct {
TraceId string
Reply interface{}
}
func NewRequest(traceId string, methodName string, args interface{}) *Request {
return &Request{
TraceId: traceId,
MethodName: methodName,
Args: args,
}
}
func NewResponse(traceId string, reply interface{}) *Response {
return &Response{
TraceId: traceId,
Reply: reply,
}
}
// If encode in GOB we should register the type of Args to prevent the GOB encode error
func (request *Request) RegisterGobArgsType() error {
edcodeStr := new(Config).GetEdcodeConf()
switch edcodeStr {
case "gob":
args := reflect.New(reflect.TypeOf(request.Args))
if args.Kind() == reflect.Ptr {
args = args.Elem()
}
gob.Register(args.Interface())
return nil
case "json":
return nil
default:
return errors.New("Unknown edcode protocol: " + edcodeStr)
}
}
// If encode in GOB we should register the type of Args to prevent the GOB encode error
func (response *Response) RegisterGobRespType() error {
edcodeStr := new(Config).GetEdcodeConf()
switch edcodeStr {
case "gob":
reply := reflect.New(reflect.TypeOf(response.Reply))
if reply.Kind() == reflect.Ptr {
reply = reply.Elem()
}
gob.Register(reply.Interface())
return nil
case "json":
return nil
default:
return errors.New("Unknown edcode protocol: " + edcodeStr)
}
}
// Return the reflect.Value type of Args
func (request *Request) MakeArgs(edcode Edcode, service Service) (reflect.Value, error) {
switch edcode.(type) {
case GobEncode:
return reflect.ValueOf(request.Args), nil
case JsonEncode:
reqArgs := request.Args.(map[string]interface{})
argv := reflect.New(service.ArgType)
err := MakeArgType(reqArgs, argv)
if err != nil {
log.Println(err.Error())
return reflect.New(nil), err
}
if argv.Kind() == reflect.Ptr {
argv = argv.Elem()
}
return argv, nil
default:
return reflect.ValueOf(request.Args), errors.New("Unknown edcode")
}
}