Go反射调用结构体方法需满足:方法导出、接收者类型匹配、参数严格一致;通过reflect.Value获取并Call执行,返回值需手动转换,建议封装安全调用函数。
Go语言的反射机制可以让你在运行时获取结构体的方法信息并动态调用,但需注意:方法必须是导出的(首字母大写),且接收者需匹配(指针或值类型要一致)。核心在于用 reflect.Value 获取方法值,再通过 Call() 执行。
只有满足以下条件的方法才能被 reflect 正确识别和调用:
reflect.ValueOf(&s)(指针),则只能调用指针接收者方法;若用 reflect.ValueOf(s)(值),则只能调用值接收者方法[]reflect.Value 必须与方法签名一致以一个简单结构体为例:
type User struct{ Name string }
func (u User) GetName() string { return u.Name }
func (u *User) SetName(name string) { u.Name = name }
调用步骤如下:
reflect.ValueOf(instance) 获取实例的反射值(注意是指针还是值)MethodByName("MethodName") 获取方法值,返回 reflect.Value(若方法不存在则为零值)method.IsValid() && method.Kind() == reflect.Func
reflect.ValueOf(arg) 包装method.Call(args),返回值是 []reflect.Value 切片反射调用的返回值始终是 []reflect.Value,需手动转换:
string,可用 ret[0].String()
int,用 ret[0].Int();返回 bool 用 ret[0].Bool()
(string, error)),ret 长度为2,分别取 ret[0].String() 和 ret[1].Interface().(error)
defer/recover 中,或提前校验方法存在性与参数类型,避免 panic可抽象出一个安全调用辅助函数:
func CallMethod(obj interface{}, methodName string, args ...interface{}) ([]interface{}, error) {
v := reflect.ValueOf(obj)
if v.Kind() == reflect.Ptr { v = v.Elem() }
method := v.MethodByName(methodName)
if !method.IsValid() { return nil, fmt.Errorf("method %s not found", methodName) }
in := make([]reflect.Value, len(args))
for i, arg := range args { in[i] = reflect.ValueOf(arg) }
out := method.Call(in)
results := make([]interface{}, len(o
ut))
for i, r := range out { results[i] = r.Interface() }
return results, nil
}
这样就能一行调用:result, _ := CallMethod(&u, "SetName", "Alice")。