Go reflect 反射实战从 Json Marshal 到 OR Mapper反射能解决很多通用化问题也是性能杀手。本文讲清 reflect 原理与边界。一、反射能做啥不知道类型 → 写通用函数JSON / YAML / XML 序列化框架自动复制字段二、反射基础importreflectvarxstruct{Namestringjson:name}{Tom}t:reflect.TypeOf(x)v:reflect.ValueOf(x)fmt.Println(t.Field(0).Tag)// json:\name\三、struct → map 通用化funcStructToMap(v any)map[string]any{out:make(map[string]any)rv:reflect.ValueOf(v)rt:rv.Type()fori:0;irt.NumField();i{f:rt.Field(i)out[f.Name]rv.Field(i).Interface()}returnout}四、ORM 简易实现funcInsert(db*sql.DB,obj any)error{t:reflect.TypeOf(obj)ift.Kind()!reflect.Struct{returnerrors.New(expect struct)}cols:[]string{}placeholders:[]string{}args:[]any{}fori:0;it.NumField();i{colsappend(cols,t.Field(i).Name)placeholdersappend(placeholders,?)argsappend(args,reflect.ValueOf(obj).Field(i).Interface())}q:fmt.Sprintf(INSERT INTO %s (%s) VALUES (%s),strings.ToLower(t.Name()),strings.Join(cols,, ),strings.Join(placeholders,, ),)_,err:db.Exec(q,args...)returnerr}五、反射 vs 反射代码生成反射动态、慢代码生成编译期、快、复杂通用代码用反射性能敏感用生成。六、reflect 包细节func(v Value)Kind()Kindfunc(v Value)Field(iint)Valuefunc(v Value)Type()Typefunc(t Type)NumField()intfunc(t Type)Field(iint)StructField七、setter / setter 通过 reflectfuncSetField(obj any,namestring,value any){v:reflect.ValueOf(obj).Elem().FieldByName(name)ifv.CanSet(){v.Set(reflect.ValueOf(value))}}八、踩坑清单未导出字段不可 setpanic指针 vs 值反射传指针才是 obj性能reflect.Value.Kind()也是较慢九、reflect.Value vs reflection.TypeSwitchswitchv:x.(type){caseint:...casestring:...}值类型判断优先 type switch。十、企业实战通用 DinD Mongo 适配器动态映射结构体到 MongofuncConvert(obj any)bson.M{m:bson.M{}t:reflect.TypeOf(obj)v:reflect.ValueOf(obj)fori:0;it.NumField();i{m[t.Field(i).Tag.Get(bson)]v.Field(i).Interface()}returnm}十一、reflection benchmarkBenchmarkDirect-8 500000 2400 ns/op 0 B/op BenchmarkReflect-8 500000 7500 ns/op 0 B/op反射慢 3x。十二、未来Go 1.24 计划加入maphash优化反射社区向代码生成迁移。十三、总结与展望反射是一把双刃剑用对则简化通用逻辑用错则拖累性能。未来代码生成 interface 优先 反射补缺的模式。十四、参考文献reflect 包Go stdlib source
