Golang Go语言中好用的反射工具库, 支持设置嵌套结构体字段, 动态函数调用等功能
介绍
在实际业务开发中, 经常需要用到反射的能力, 比如结合远程配置动态修改结构体的字段, 这样无需发布即可实现功能变更, 再比如拓展插件的场景, 使用表驱动的方式调用一些异构的函数(无法抽象为接口)等. 这里对常用的操作进行了 getter, setter 的封装, 并增强了一些能力, 比如支持设置多层嵌套结构体的字段, 针对结构体指针自动创建等.
地址: https://github.com/morrisxyang/xreflect
中文文档: https://github.com/morrisxyang/xreflect/blob/main/README_CN.md
如果觉得有用欢迎 Star 和 PR, 有问题直接提 Issue
xreflect
一个简单的, 易用的反射工具库.
主要支持如下特性:
-
设置结构体字段值, 支持通过路径比如
A.B.C
设置嵌套结构体字段的值 -
获取结构体字段的值, 类型, Tag 等.
-
遍历结构体所有字段, 支持
select
模式和range
模式, 如果使用深度遍历方法比如FieldsDeep
将遍历所有嵌套结构. -
函数调用, 方法调用, 支持可变参数.
-
新建实例, 判断接口实现等等.
安装和文档
安装命令 go get github.com/morrisxyang/xreflect
.
文档见 https://pkg.go.dev/github.com/morrisxyang/xreflect
快速开始
设置嵌套结构体字段值
person := &Person{
Name: "John",
Age: 20,
Country: Country{
ID: 0,
Name: "Perk",
},
}
_ = SetEmbedField(person, “Country.ID”, 1)
// Perk’s ID: 1
fmt.Printf(“Perk’s ID: %d \n”, person.Country.ID)
调用函数
var addFunc = func(nums ...int) int {
var sum int
for _, num := range nums {
sum += num
}
return sum
}
res, _ := CallFunc(addFunc, 1, 2, 3)
// 6
fmt.Println(res[0].Interface())
核心方法
FieldX
- func Field(obj interface{}, fieldName string) (reflect.Value, error)
- func FieldValue(obj interface{}, fieldName string) (interface{}, error)
- func EmbedField(obj interface{}, fieldPath string) (reflect.Value, error)
- func EmbedFieldValue(obj interface{}, fieldPath string) (interface{}, error)
- func Fields(obj interface{}) (map[string]reflect.Value, error)
- func FieldsDeep(obj interface{}) (map[string]reflect.Value, error)
- func RangeFields(obj interface{}, f func(string, reflect.StructField, reflect.Value) bool) error
- func SelectFields(obj interface{}, f func(string, reflect.StructField, reflect.Value) bool) (map[string]reflect.Value, error)
- etc.
SetX
-
func SetEmbedField(obj interface{}, fieldPath string, fieldValue interface{}) error
-
func SetField(obj interface{}, fieldName string, fieldValue interface{}) error
-
func SetPrivateField(obj interface{}, fieldName string, fieldValue interface{}) error
-
etc.
StrcutFieldX
-
func StructField(obj interface{}, fieldName string) (reflect.StructField, error)
-
func StructFieldTagValue(obj interface{}, fieldName, tagKey string) (string, error)
-
func EmbedStructField(obj interface{}, fieldPath string) (reflect.StructField, error)
-
func StructFields(obj interface{}) ([]reflect.StructField, error)
-
func StructFieldsFlatten(obj interface{}) ([]reflect.StructField, error)
-
func RangeStructFields(obj interface{}, f func(int, reflect.StructField) bool) error
-
etc.
FuncX
-
func CallFunc(fn interface{}, args ...interface{}) ([]reflect.Value, error)
-
func CallMethod(obj interface{}, method string, params ...interface{}) ([]reflect.Value, error)
-
etc.
Others
- func NewInstance(obj interface{}) interface{}
- func Type(obj interface{}) reflect.Type
- func TypePenetrateElem(obj interface{}) reflect.Type
- func Value(obj interface{}) reflect.Value
- func ValuePenetrateElem(obj interface{}) reflect.Value
- etc.
FAQ
Field
和 StrcutField
的区别是?
Field
返回 reflect.Value, StrcutField
返回 reflect.StrcutField.
Golang Go语言中好用的反射工具库, 支持设置嵌套结构体字段, 动态函数调用等功能
更多关于Golang Go语言中好用的反射工具库, 支持设置嵌套结构体字段, 动态函数调用等功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html
👍🏻
更多关于Golang Go语言中好用的反射工具库, 支持设置嵌套结构体字段, 动态函数调用等功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
欢迎提出需求和建议
你们反射用得很多吗? 性能差不少吧
是的, golang 的反射性能确实比直接调低很多, 不过是否使用要考虑 2 个方面.
1. 场景, 是极致追求性能还是普通业务, 这其实是在性能和动态修改的灵活能力之间做取舍, 我举个例子, 在 B 端场景, 往往会更考虑灵活, 因为 B 侧业务甚至是延迟 10min 都可以接受.
2. 性能对比的尺度, 举个例子, 一个操作可能是 100ns, 用了反射之后是 500ns, 这是 5 倍, 但整体接口耗时是 200ms, 对整体的影响微乎其微, 这时可以考虑为了业务灵活性的支持引入反射.
是的, 合适的地方用, 能减少非常多重复的代码, 对吧
是的, 一些场景使用反射进行动态组装可以减少重复代码, 不过我自己体会的话, 减少重复代码是一个表现不是目的, 更多的是实现一些逻辑的配置化.
丰富一下例子呗,看看你怎么用的,让我学习扩展思路
README.md 的例子是吗
#8 对的, 不过我在看文档和源码+Test, 基本清楚了.
readme 里面的例子 可以考虑丰富一些
在Golang中,反射是一个强大的工具,它允许开发者在运行时检查和操作对象的类型、变量、函数等。针对你提到的需求,即寻找一个支持设置嵌套结构体字段和动态函数调用等功能的反射工具库,我推荐以下几个:
-
xreflect:
- 一个简单易用的反射工具库,支持设置结构体字段值(包括嵌套结构体)、获取结构体字段信息、函数调用、方法调用等。
- 可以通过
go get github.com/morrisxyang/xreflect
安装,详细文档参见xreflect的GitHub页面。
-
go-reflect:
- 由开发者Goccy发起的项目,旨在优化和简化Go语言中的反射操作。
- 提供了更高效、更易用的反射操作,如根据字符串名创建reflect.Type实例、按tag过滤和设置结构体字段等。
- 引入了缓存系统以提升性能,完全兼容Go标准库reflect。
这两个库都极大地增强了Go标准库reflect的功能,提供了更丰富、更便捷的反射操作。你可以根据项目的具体需求选择合适的工具库。无论选择哪个库,都建议详细阅读其文档,以充分利用其提供的强大功能。