← 修改值 | 性能分析 →

反射方法 - 方法反射详解

通过反射可以检查和调用结构体方法,这是实现依赖注入、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 供后续调用
    }
}

📖 延伸阅读