当前位置: 首页 > news >正文

Go 语言学习之 reflect

概念:

        在Go 语言中,reflect 可以用来在运行期间获取对象的类型信息和内存架构,reflect 操作所需的全部信息都源自接口变量,接口变量除了存储自身类型外,还会保存实际对象的类型数据,reflect通过TypeOf 和ValueOf 函数,将任何传入的对象转换位接口类型。

使用反射获取对象的类型:

func reflect.TypeOf(i interface{}) reflect.Type

获取对象的类型信息

type A intfunc main() {var a A = 1t := reflect.TypeOf(a)fmt.Println(t.Name(), t.Kind())
}

输出的结果:

        

需要注意的是,Name是真实类型,Kind 是真实类型的基础结构类别,在类型判断时要注意区分。

        传入的参数对象区分基本类型和指针类型

func main() {b := 2t1, t2 := reflect.TypeOf(b), reflect.TypeOf(&b)fmt.Println(t1, t2, t1 == t2, t2.Elem())fmt.Println(t1.Kind(), t2.Kind())fmt.Println(t1 == t2.Elem())
}

输出的结果:

上述的代码中,我们使用看Elem方法返回指针的基类型,此外,Elem 方法还可以返回数据,slice 、map 、chan 的基类型。

使用反射操作struct

遍历结构体:

遍历结构体的字段,需要先获取结构体指针的基类型

type student struct {name  stringscore int
}func main() {var s studentt := reflect.TypeOf(&s)if t.Kind() == reflect.Ptr {t = t.Elem()}fmt.Println(t.NumField())for i := 0; i < t.NumField(); i++ {structField := t.Field(i)fmt.Println(structField.Name, structField.Type)}
}

输入结果:

提取struct tag

        一般用于ORM 映射,数据格式验证。

type user struct {name string `form:"user_name"`age  int    `form:"user_age"`
}func main() {var user1 usert := reflect.TypeOf(user1)for i := 0; i < t.NumField(); i++ {structField := t.Field(i)fmt.Println(structField.Name, structField.Tag.Get("form"))}
}

输出结果:

使用反射获取和修改对象的值:

func reflect.ValueOf(i interface{}) reflect.Value
type animal struct {Name stringage  int
}func main() {var cat animalv := reflect.ValueOf(&cat).Elem()fmt.Printf("v:%v type:%v kind:%v\n", v, v.Type(), v.Kind())v.FieldByName("Name").SetString("kity")fmt.Printf("v:%v type:%v kind:%v\n", v, v.Type(), v.Kind())
}

输出结果:

通过代码演示,发现ValueOf 可以获取对象的值

        我们知道修改对象的变量,需要传入指针,但是因为接口变量存储的指针的不可以寻址和设置变量的,所以还需要通过Elem 获取目标对象,

        非导出字段的值不能修改

使用反射动态调用方法:

        固定参数,使用call ,只需按照参数雷彪传参即可

演示代码:

type member struct {
}func (m member) MemberInfo(name string, score int) string {mInfo := fmt.Sprintf("姓名:%s 积分:%d\n", name, score)return mInfo
}func main() {var m1 memberv := reflect.ValueOf(&m1)m := v.MethodByName("MemberInfo")param := []reflect.Value{reflect.ValueOf("frank"),reflect.ValueOf(88),}result := m.Call(param)for _, v := range result {fmt.Println(v)}
}

输出结果:

可变参数,使用CallSlice,仅需一个 []interface{} 即可。

        演示代码:

type person struct {
}func (p person) Hobby(name string, hobby ...interface{}) string {myHooby := fmt.Sprintf("I am %v, My hooby is %v", name, hobby)return myHooby
}func main() {var p1 personv := reflect.ValueOf(&p1)m := v.MethodByName("Hobby")param := []reflect.Value{reflect.ValueOf("lucy"),reflect.ValueOf("singing"),reflect.ValueOf("dancing0"),}result := m.Call(param)fmt.Println(result)param = []reflect.Value{reflect.ValueOf("lucy"),reflect.ValueOf([]interface{}{"singing", "dancing"}),}result = m.CallSlice(param)fmt.Println(result)
}

输出结果:

http://www.lryc.cn/news/596842.html

相关文章:

  • Spring--事务传播行为(REQUIRED / REQUIRES_NEW / NESTED)
  • 【图像处理基石】如何对遥感图像进行目标检测?
  • 【Linux | 网络】应用层(HTTPS)
  • 【数据结构初阶】--树和二叉树先导篇
  • 床上肢体康复机器人的机械结构设计cad【7张】三维图+设计说明书
  • #Linux内存管理# 在一个播放系统中同时打开几十个不同的高清视频文件,发现播放有些卡顿,打开视频文件是用mmap函数,请简单分析原因。
  • GEMINUS 和 Move to Understand a 3D Scene
  • 基于 XGBoost 与 SHAP 的医疗自动化办公与可视化系统(下)
  • 【计算机三级网络】——选择题高频考点(第一篇)
  • SQL基础⑧ | 表格篇
  • Python设计模式 - 桥接模式
  • 腾讯iOA:企业软件合规与安全的免费守护者
  • 炬森精密:缓冲滑轨的创新力量,重塑家居静音与安全新体验
  • LeetCode二叉树的公共祖先
  • 亚远景-传统功能安全VS AI安全:ISO 8800填补的标准空白与实施难点
  • 漏洞生命周期管理:从发现到防护的全流程方案
  • 基于Python(Django)+MongoDB实现的(Web)新闻采集和订阅系统
  • #C语言——学习攻略:操作符的探索(二)
  • ES6 标签模板:前端框架的灵活利器
  • mongodb的备份和还原(精简)
  • HarmonyOS Flutter Boost完全接入手册:爬完所有坑的实战指南
  • DeepSeek-R1大模型实战:AI编程助手如何提升开发效率
  • JVM、Dalvik、ART区别
  • 用Python实现卷积神经网络(一)
  • 电子电气架构 --- 汽车软件全生命周期
  • Java 堆(优先级队列)
  • 226.翻转二叉树
  • JAVA_EVLEN-面向对象高级二
  • 【C语言进阶】动态内存管理(2)
  • 新手向:Idea的使用技巧