我正在Go中编写RPC服务。我不知道如何将struct方法转换为Handler
函数。
我尝试过的事情:
type TestService struct{}
func (TestService) Foo(a int) error {
return nil
}
type Handle func(a int) error
func TestHandle(t *testing.T) {
ts := new(TestService)
val := reflect.ValueOf(ts)
// typ := reflect.TypeOf(ts)
// fmt.Println(val.Method(0).Interface())
// fmt.Println(val.Method(0).Type().ConvertibleTo(reflect.TypeOf(new(Handle))))
switch reflect.Indirect(val).Method(0).Interface().(type) {
case Handle:
fmt.Println(" okokok " )
default:
fmt.Println(reflect.Indirect(val).Method(0).Type())
}
}
但是失败了。我该怎么办?
答案 0 :(得分:1)
方法TestService.Foo
的类型为func(a int) error
,与类型Handle
不同(Handle
具有相同的基础类型,但它是一种新的,独特的类型)。
您必须检查此确切类型:
case func(a int) error:
fmt.Println(" okokok ")
进行此更改后,输出将为:
=== RUN TestHandle
okokok
--- PASS: TestHandle (0.00s)
PASS
在Go Playground上尝试。
请注意,您可以对type assertion执行相同的操作,例如:
if _, ok := reflect.Indirect(val).Method(0).Interface().(func(a int) error); ok {
fmt.Println(" okokok ")
}
在Go Playground上尝试这个。
还要注意,如果您确实想使用Handle
类型的定义,则可以检查函数值是否为Handle
类型的变量的assignable。使用反射,此检查实质上意味着方法的类型是否可分配给Handle
的类型。
它是这样的:
th := reflect.TypeOf(Handle(nil))
if reflect.Indirect(val).Method(0).Type().AssignableTo(th) {
fmt.Println(" okokok ")
}
在Go Playground上尝试这个。
以上解决方案仅检查给定方法是否为给定函数类型。如果还需要函数值(因此可以调用它),则可以这样做:
使用类型开关(Go Playground)时:
switch hf := reflect.Indirect(val).Method(0).Interface().(type) {
case func(a int) error:
fmt.Println(" okokok ", hf(0))
default:
fmt.Println(reflect.Indirect(val).Method(0).Type())
}
使用类型断言(Go Playground)时:
if hf, ok := reflect.Indirect(val).Method(0).Interface().(func(a int) error); ok {
fmt.Println(" okokok ", hf(0))
}
使用Value.Convert()
(Go Playground):
m := reflect.Indirect(val).Method(0)
th := reflect.TypeOf(Handle(nil))
if m.Type().AssignableTo(th) {
var hf Handle = m.Convert(th).Interface().(Handle)
fmt.Println(" okokok ", hf(0))
}