package component import ( "reflect" "unicode" "unicode/utf8" ) var ( typeOfError = reflect.TypeOf((*error)(nil)).Elem() typeOfBytes = reflect.TypeOf(([]byte)(nil)) // TODO cycle not allow IConnection typeOfConnection = reflect.TypeOf(([]byte)(nil)) ) func isExported(name string) bool { w, _ := utf8.DecodeRuneInString(name) return unicode.IsUpper(w) } func isExportedOrBuiltinType(t reflect.Type) bool { for t.Kind() == reflect.Ptr { t = t.Elem() } // PkgPath will be non-empty even for an exported type, // so we need to check the type name as well. return isExported(t.Name()) || t.PkgPath() == "" } func isHandlerMethod(method reflect.Method) bool { mt := method.Type // 必须是可导出的 if isExportedOrBuiltinType(mt) { return false } // 必须具有3个入参: receiver, *Request, []byte/pointer // receiver指代 func (*receiver) xxx() 的receiver部分 if mt.NumIn() != 3 { return false } // 至少要有一个出参 且是error if mt.NumOut() < 1 { return false } // 第一个显式入参必须是实现了IConnection的具体类的指针类型 if t1 := mt.In(1); t1.Kind() != reflect.Ptr || t1 != typeOfConnection { return false } // 第二个显式入参必须是 []byte 或者 任意pointer if t2 := mt.In(2); t2.Kind() != reflect.Ptr || t2 != typeOfBytes { return false } // 最后一个出参必须是error if o1 := mt.Out(mt.NumOut() - 1); o1 != typeOfError { return false } return true }