Last active
April 28, 2016 09:36
-
-
Save zhangyuchi/a92ef3f62069074e6b162ea58f1dc541 to your computer and use it in GitHub Desktop.
注册本地回调函数时如何应用reflect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func (server *Server) Register(rcvr interface{}) error { | |
s := new(service) | |
s.typ = reflect.TypeOf(rcvr) | |
s.rcvr = reflect.ValueOf(rcvr) | |
sname := reflect.Indirect(s.rcvr).Type().Name() | |
if sname == "" { | |
s := "rpc.Register: no service name for type " + s.typ.String() | |
log.Print(s) | |
return errors.New(s) | |
} | |
if !isExported(sname) { | |
s := "rpc.Register: type " + sname + " is not exported" | |
log.Print(s) | |
return errors.New(s) | |
} | |
if _, present := server.serviceMap[sname]; present { | |
return errors.New("rpc: service already defined: " + sname) | |
} | |
s.name = sname | |
// Install the methods | |
s.method = suitableMethods(s.typ, true) | |
if len(s.method) == 0 { | |
str := "" | |
// To help the user, see if a pointer receiver would work. | |
method := suitableMethods(reflect.PtrTo(s.typ), false) | |
if len(method) != 0 { | |
str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)" | |
} else { | |
str = "rpc.Register: type " + sname + " has no exported methods of suitable type" | |
} | |
log.Print(str) | |
return errors.New(str) | |
} | |
server.serviceMap[s.name] = s | |
return nil | |
} | |
// suitableMethods returns suitable Rpc methods of typ, it will report | |
// error using log if reportErr is true. | |
func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { | |
methods := make(map[string]*methodType) | |
for m := 0; m < typ.NumMethod(); m++ { | |
method := typ.Method(m) | |
mtype := method.Type | |
mname := method.Name | |
// Method must be exported. | |
if method.PkgPath != "" { | |
continue | |
} | |
// Method needs three ins: receiver, *args, *reply. | |
if mtype.NumIn() != 3 { | |
if reportErr { | |
log.Println("method", mname, "has wrong number of ins:", mtype.NumIn()) | |
} | |
continue | |
} | |
// First arg need not be a pointer. | |
argType := mtype.In(1) | |
if !isExportedOrBuiltinType(argType) { | |
if reportErr { | |
log.Println(mname, "argument type not exported:", argType) | |
} | |
continue | |
} | |
// Second arg must be a pointer. | |
replyType := mtype.In(2) | |
if replyType.Kind() != reflect.Ptr { | |
if reportErr { | |
log.Println("method", mname, "reply type not a pointer:", replyType) | |
} | |
continue | |
} | |
// Reply type must be exported. | |
if !isExportedOrBuiltinType(replyType) { | |
if reportErr { | |
log.Println("method", mname, "reply type not exported:", replyType) | |
} | |
continue | |
} | |
// Method needs one out. | |
if mtype.NumOut() != 1 { | |
if reportErr { | |
log.Println("method", mname, "has wrong number of outs:", mtype.NumOut()) | |
} | |
continue | |
} | |
// The return type of the method must be error. | |
if returnType := mtype.Out(0); returnType != typeOfError { | |
if reportErr { | |
log.Println("method", mname, "returns", returnType.String(), "not error") | |
} | |
continue | |
} | |
methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType} | |
} | |
return methods | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment