V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
atVoid
V2EX  ›  Go 编程语言

Golang 好用的反射工具库, 支持设置嵌套结构体字段, 动态函数调用等功能.

  •  
  •   atVoid ·
    morrisxyang · 237 天前 · 979 次点击
    这是一个创建于 237 天前的主题,其中的信息可能已经有所发展或是发生改变。

    介绍

    在实际业务开发中, 经常需要用到反射的能力, 比如结合远程配置动态修改结构体的字段, 这样无需发布即可实现功能变更, 再比如拓展插件的场景, 使用表驱动的方式调用一些异构的函数(无法抽象为接口)等. 这里对常用的操作进行了 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

    SetX

    StrcutFieldX

    FuncX

    Others

    FAQ

    FieldStrcutField 的区别是?

    Field 返回 reflect.Value, StrcutField 返回 reflect.StrcutField.

    10 条回复    2023-10-01 14:21:17 +08:00
    asmoker
        1
    asmoker  
       237 天前
    👍🏻
    atVoid
        2
    atVoid  
    OP
       236 天前
    欢迎提出需求和建议
    daiv
        3
    daiv  
       236 天前
    你们反射用得很多吗? 性能差不少吧
    atVoid
        4
    atVoid  
    OP
       235 天前
    @daiv 是的, golang 的反射性能确实比直接调低很多, 不过是否使用要考虑 2 个方面.
    1. 场景, 是极致追求性能还是普通业务, 这其实是在性能和动态修改的灵活能力之间做取舍, 我举个例子, 在 B 端场景, 往往会更考虑灵活, 因为 B 侧业务甚至是延迟 10min 都可以接受.
    2. 性能对比的尺度, 举个例子, 一个操作可能是 100ns, 用了反射之后是 500ns, 这是 5 倍, 但整体接口耗时是 200ms, 对整体的影响微乎其微, 这时可以考虑为了业务灵活性的支持引入反射.
    daiv
        5
    daiv  
       235 天前
    @daiv 是的, 合适的地方用, 能减少非常多重复的代码, 对吧
    atVoid
        6
    atVoid  
    OP
       233 天前
    @daiv 是的, 一些场景使用反射进行动态组装可以减少重复代码, 不过我自己体会的话, 减少重复代码是一个表现不是目的, 更多的是实现一些逻辑的配置化.
    daiv
        7
    daiv  
       233 天前
    @atVoid 丰富一下例子呗,看看你怎么用的,让我学习扩展思路
    atVoid
        8
    atVoid  
    OP
       232 天前
    @daiv README.md 的例子是吗
    daiv
        9
    daiv  
       232 天前
    @atVoid #8 对的, 不过我在看文档和源码+Test, 基本清楚了.

    readme 里面的例子 可以考虑丰富一些
    atVoid
        10
    atVoid  
    OP
       212 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   798 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:37 · PVG 04:37 · LAX 13:37 · JFK 16:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.