反射获取函数类型必须传函数值而非调用结果,即用 reflect.TypeOf(myFunc) 而非 reflect.TypeOf(myFunc());方法类型 NumIn() 包含 receiver,变参需用 IsVariadic() 判断,参数类型需严格匹配 Call 才能成功。

传函数名别带括号,否则拿到的是返回值类型
直接传 reflect.TypeOf(myFunc()) 会 panic 或返回错误类型,因为括号表示调用,myFunc() 是执行结果,不是函数本身。反射要分析的是函数签名,必须传函数值——也就是不带括号的标识符或变量名。
-
reflect.TypeOf(myFunc)✅ 正确:得到func(int, string) bool类型 -
reflect.TypeOf(myFunc())❌ 错误:如果myFunc返回int,这里拿到的就是reflect.Int,不是函数类型 - 匿名函数也行:
reflect.TypeOf(func(x int) {})合法,但闭包捕获的变量无法通过反射还原 - 未导出方法(小写开头)无法被
MethodByName获取,IsValid()会返回false
NumIn() 返回参数个数,但 method 会多算一个 receiver
对普通函数,t.NumIn() 就是你写的形参个数;但对结构体方法(比如 (s *S) Foo(a, b int)),reflect.TypeOf(s.Foo).NumIn() 返回的是 3——*S(receiver)+ a + b。这不是 bug,是 Go 反射把 method 当作带接收者的函数来处理。
- 判断是否为 method:看
t.In(0).PkgPath()是否为空(receiver 通常无包路径),或用reflect.ValueOf(fn).Kind() == reflect.Func配合t.NumIn() > 0做启发式判断 - 想排除 receiver:循环时从
i = 1开始取t.In(i),前提是确认它是 method - 变参函数如
func(a int, b ...string),t.NumIn()返回 2,t.IsVariadic()为true,最后一个参数类型是[]string
In(i) 拿到的是 reflect.Type,不是字符串,别直接 fmt.Print
t.In(i) 返回的是 reflect.Type 对象,它不等于参数名,也不等于可读字符串。调 .String() 能看到完整类型签名(如 *main.MyStruct 或 []int),但对内置类型(int、string).Name() 会返回空字符串,得靠 .Kind() 判断基础类别。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 区分命名类型和未命名类型:
type MyInt int的.Name()是"MyInt",而int的.Name()是空,此时应看.Kind() == reflect.Int - 指针、切片、接口等复合类型,
.String()显示完整形态,例如*int、[]string、io.Reader - 嵌套类型(如结构体字段、map value)需递归调
.Elem()或.Key()/Value(),不能只靠一层In(i)
Call 之前必须手动对齐参数数量和类型,没有自动转换
reflect.Value.Call 不接受原始 Go 值,只认 []reflect.Value,且每个元素的类型必须与 t.In(i) 完全一致——包括是否是指针、是否实现了某接口、底层类型是否匹配。错一点就 panic,错误信息通常是 reflect: Call using zero Value 或 reflect: Call of function with wrong argument count。
立即学习“go语言免费学习笔记(深入)”;
- 务必先校验:
if len(args) != t.NumIn() { panic("arg count mismatch") } - 基础类型用
reflect.ValueOf(x);指针类型用reflect.ValueOf(&x);接口值需确保其底层类型能赋值给目标参数 - 传
nil指针或空切片时,不能直接传nil,得用reflect.Zero(t.In(i))构造对应类型的零值 - Go 反射完全不保留参数名,所有依赖「形参名自动绑定」的逻辑(如 HTTP query 解析)都得靠 struct tag、代码生成或 AST 解析实现

















