

新闻资讯
技术学院泛型解决编译期类型复用,反射解决运行时类型未知;泛型零开销但无法处理字段级动态操作,反射灵活却有性能损耗和panic风险,二者分层协作而非替代。
泛型解决编译期类型复用,反射解决运行时类型未知——两者定位不同,不是替代关系,而是分层协作。
泛型在 Go 1.18+ 中通过类型参数 T 实现,编译器会为每个实际类型(如 int、string)生成专用函数版本,不依赖 interface{} 或运行时类型检查。
func Print[T any](v T) 传入 int 就只能传 int,错类型直接报错reflect.ValueOf、reflect.Type 等,性能接近手写单类型函数func Sum[T ~int | ~float64](a, b T) T {
return a + b
}
// 编译后生成 Sum[int] 和 Sum[float64] 两个独立函数,无反射逻辑
反射基于 interface{} 底层的类型信息,在程序运行时通过 reflect.TypeOf 和 reflect.ValueOf 获取并操作值,适用于真正动态的场景。
reflect 包支持,带来明显性能损耗v.Elem()、对不可寻址值调用 v.Set()、访问未导出字段等v := reflect.ValueOf(struct{ Name string }{Name: "Alice"})
fmt.Println(v.Field(0).Interface()) // "Alice"
// 但如果字段是小写 name,则 v.Field(0).Interface() 会 panic:cannot interface with unexported field
关键看「类型是否在编译期可知」以及「操作是否需要突破类型边界」。
Stack[T])、切片工具(Map[T, U])、约束明确的校验(Equal[T comparable])json:"name")、动态调用方法(v.MethodByName("Save").Call(...))func Inspect[T any](t T) { tType := reflect.TypeOf(t) } —— 这样既保编译期类型入口,又留运行时探查能力即使写了泛型,一旦涉
及结构体字段级操作(如忽略某个字段、按 tag 提取值),仍逃不开反射。常见误判是以为加了 [T any] 就能避免 reflect。
T 在函数体内仍是黑盒:你无法用 len(T) 或 T.Name 访问结构体字段,必须用 reflect.ValueOf(t).NumField()
"Email" 去取结构体对应字段,必须靠反射真正复杂的通用库(如 validator、sqlx、mapstructure)都是泛型定义入口 + 反射实现核心,而不是二选一。