反射方法 - 方法反射详解
通过反射可以检查和调用结构体方法,这是实现依赖注入、RPC 框架等高级功能的基础。掌握方法反射需要理解 Method 和 FuncType。
方法信息
📝 获取方法信息
package main
import (
"fmt"
"reflect"
)
type Calculator struct{}
func (c Calculator) Add(a, b int) int {
return a + b
}
func (c Calculator) Sub(a, b int) int {
return a - b
}
func (c Calculator) Mul(a, b int) int {
return a * b
}
func main() {
var c Calculator
t := reflect.TypeOf(c)
// 方法数量
fmt.Printf("NumMethod: %d\n", t.NumMethod())
// 遍历所有方法
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
fmt.Printf("Method %d: %s\n", i, method.Name)
fmt.Printf(" Type: %v\n", method.Type)
fmt.Printf(" In: %d, Out: %d\n",
method.Type.NumIn(), method.Type.NumOut())
}
}
调用方法
📝 反射调用方法
package main
import (
"fmt"
"reflect"
)
type Greeter struct {
Name string
}
func (g Greeter) Greet() string {
return "Hello, " + g.Name
}
func (g Greeter) GreetWith(prefix string) string {
return prefix + ", " + g.Name
}
func main() {
g := Greeter{Name: "Alice"}
v := reflect.ValueOf(g)
// 获取方法
greetMethod := v.MethodByName("Greet")
// 调用无参数方法
results := greetMethod.Call(nil)
fmt.Println(results[0].String())
// 调用有参数方法
greetWithMethod := v.MethodByName("GreetWith")
args := []reflect.Value{
reflect.ValueOf("Hi"),
}
results = greetWithMethod.Call(args)
fmt.Println(results[0].String())
}
方法类型
📝 方法类型信息
func inspectMethod(v interface{}, methodName string) {
val := reflect.ValueOf(v)
method := val.MethodByName(methodName)
if !method.IsValid() {
fmt.Printf("Method %s not found\n", methodName)
return
}
t := method.Type()
fmt.Printf("Method: %s\n", methodName)
fmt.Printf("NumIn: %d\n", t.NumIn())
fmt.Printf("NumOut: %d\n", t.NumOut())
// 输入参数类型
for i := 0; i < t.NumIn(); i++ {
fmt.Printf(" In[%d]: %v\n", i, t.In(i))
}
// 输出参数类型
for i := 0; i < t.NumOut(); i++ {
fmt.Printf(" Out[%d]: %v\n", i, t.Out(i))
}
}
实用模式
📝 自动注册处理器
type Handler interface{}
type UserService struct{}
func (s *UserService) GetUser(id int) {}
func (s *UserService) CreateUser(name string) {}
func (s *UserService) DeleteUser(id int) {}
func RegisterHandlers(handler Handler) {
t := reflect.TypeOf(handler)
v := reflect.ValueOf(handler)
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
methodVal := v.Method(i)
fmt.Printf("Registered: %s\n", method.Name)
// 存储 methodVal 供后续调用
}
}