go语言——实现函数名到函数处理的映射关系(反射的应用)

摘要:
模拟这样的场景:当我们知道要执行的操作的名称并将其作为参数传入时,如何使用该名称执行相应的函数处理?解决方案:(在这里设置一个结构a,其变量a,对应的函数是fun1和fun2)①: 首先,在编码过程中,我们可以在“同一结构”中实现相应的处理函数,使它们的函数名和相应的处理功能与映射结构映射;② : 通过创建结构的变量,通过反射(vf:=reflect.ValueOf(a))获得val

模拟这样一个场景:当我们知道我们要执行操作的名字,让其作为参数传入,如何通过这个名字取执行相应的函数处理呢?

解决方法:(这里设定一个结构A,其变量a,实现相应函数为fun1、fun2)

  ①:首先在编码过程中,我们可以将相应的处理函数进行“同一结构”实现,让其函数名和相应处理函数用map结构形成映射;

  ②:通过创建该结构体的变量,通过反射(vf :=reflect.ValueOf(a))获取value类型的值,在获得其类型(vft :=vf.Type())

  ③:读取方法的数量,进行遍历;

  ④:利用map结构实现名字与函数的对应

  for i := 0; i < mNum; i++ {
        mName := vft.Method(i).Name
        fmt.Println("index:", i, " MethodName:", mName)
        crMap[mName] = vf.Method(i) //<<<
    }

解释:因为Type类型接口当中有对应的成员函数(相应红色的成员函数

type Type interface {
    // Kind返回该接口的具体分类
    Kind() Kind
    // Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
    Name() string
    // PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64"
    // 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回""
    PkgPath() string
    // 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64")
    // 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。
    String() string
    // 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof
    Size() uintptr
    // 返回当从内存中申请一个该类型值时,会对齐的字节数
    Align() int
    // 返回当该类型作为结构体的字段时,会对齐的字节数
    FieldAlign() int
    // 如果该类型实现了u代表的接口,会返回真
    Implements(u Type) bool
    // 如果该类型的值可以直接赋值给u代表的类型,返回真
    AssignableTo(u Type) bool
    // 如该类型的值可以转换为u代表的类型,返回真
    ConvertibleTo(u Type) bool
    // 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panic
    Bits() int
    // 返回array类型的长度,如非数组类型将panic
    Len() int
    // 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panic
    Elem() Type
    // 返回map类型的键的类型。如非映射类型将panic
    Key() Type
    // 返回一个channel类型的方向,如非通道类型将会panic
    ChanDir() ChanDir
    // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
    NumField() int
    // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
    Field(i int) StructField
    // 返回索引序列指定的嵌套字段的类型,
    // 等价于用索引中每个值链式调用本方法,如非结构体将会panic
    FieldByIndex(index []int) StructField
    // 返回该类型名为name的字段(会查找匿名字段及其子字段),
    // 布尔值说明是否找到,如非结构体将panic
    FieldByName(name string) (StructField, bool)
    // 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panic
    FieldByNameFunc(match func(string) bool) (StructField, bool)
    // 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真
    // 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片)
    // 如非函数类型将panic
    IsVariadic() bool
    // 返回func类型的参数个数,如果不是函数,将会panic
    NumIn() int
    // 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panic
    In(i int) Type
    // 返回func类型的返回值个数,如果不是函数,将会panic
    NumOut() int
    // 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panic
    Out(i int) Type
    // 返回该类型的方法集中方法的数目
    // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;
    // 匿名字段导致的歧义方法会滤除
    NumMethod() int
    // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic
    // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
    // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
    Method(int) Method
    // 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法
    // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
    // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
    MethodByName(string) (Method, bool)
    // 内含隐藏或非导出方法
}
type Method struct {
    // Name是方法名。PkgPath是非导出字段的包路径,对导出字段该字段为""。
    // 结合PkgPath和Name可以从方法集中指定一个方法。
    // 参见http://golang.org/ref/spec#Uniqueness_of_identifiers
    Name    string
    PkgPath string
    Type  Type  // 方法类型
    Func  Value // 方法的值
    Index int   // 用于Type.Method的索引
}

免责声明:文章转载自《go语言——实现函数名到函数处理的映射关系(反射的应用)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇GDAL源码剖析(九)之GDAL体系架构JimuReport积木报表 — API数据源报表制作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Vert X 干法总结

Vert X优势:   1. 与基于阻塞 I/O 的传统堆栈和框架相比,以更少的资源处理更多的请求。Vert.x 非常适合各种执行环境,包括虚拟机和容器等受限环境。   2. Vert.x 是一个工具包,不是一个框架,所以它自然是非常可组合和可嵌入的(不同语言都可以)。     Vert.x运行在Java虚拟机上,支持多种编程语言,Vert.x是高度模块化...

thinkphp 常见问题

0.写在最前面的不断更新 (1)trace不起作用 A:必须要输出到模板,才会有trace信息 (2)提示“您浏览的页面暂时发生了错误!请稍后再试~” A:检查控制器(看看能进到控制器没有,设断点输出一下。如果没有。检查控制器名字,路径对了没有?) (3)Model:relation您所请求的方法不存在! A:这没什么好说的了,检查方法。 (4)神马都检查...

java责任链模式

简单解释:简单来说就是该设计模式用于对某个对象或者请求进行一系列的处理,这些处理逻辑正好组成一个链条 传统实现 假设这样的场景:传入了一段内容,需要对这段文本进行加工;比如过滤敏感词、错别字修改、最后署上版权等操作。 常见的写法如下: public class Main { public static void main(String[] args) {...

使用阿里ARouter路由实现组件化(模块化)开发流程

Android平台中对页面、服务提供路由功能的中间件,我的目标是 —— 简单且够用。 这是阿里对Arouter的定位,那么我们一起来梳理一下Arouter使用流程,和使用中我所遇到的一些问题! 先来看看有哪些功能 模块化的要解决的问题 模块间页面跳转(路由); 模块间事件通信; 模块间服务调用; 模块的独立运行; 模块间页面跳转路由拦截(登录) 其...

Java中Cookie常用操作类(Spring中操作Cookie)

说明:Cookie下用Key取值没有快速的方法,只能便利循环去取。 技巧:置0则cookie会立即删除,设置-1,负值则会在关闭浏览器后删除。切记一定要增加路径:setPath("/"),不然不会生效。在获取Cookie时要看下是否设置了域名:setDomain,不然本地调试时获取不到。 Cookie 的限制: 大多数浏览器支持最大为4096字节(4KB)...

response的响应头相关方法

响应头:Content-Type、Refresh、Location等等    头就是一个键值对!可能会存在一个头(一个名称,一个值),也可能会存在一个头(一个名称,多个值!)    > *****setHeader(String name, String value):适用于单值的响应头,例如:response.setHeader("aaa", "A...