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

[go 反射] 入门

[go 反射] 入门

首先认识go 反射的两大概念,反射之路少不了他们

  • reflect.Type(接口)获取类型,和列名就找它
  • reflect.Value(结构体)获取值,设置值找它

[tips] 通常是用这两者手底下的方法,reflect.Value结构体中有什么自行查看

演示

获取其类型(类型的准确识别定位是反射之路的基本功)

import ("reflect""fmt"
)
type One struct{One string `name:"one"`Two int     `age:"age"`
}
func main(){var(one Onetwo string)otp:=reflect.TypeOf(one)ttp:=reflect.TypeOf(two)fmt.Println(otp.Kind(),ttp.Kind())//Kind负责输出基本类型,int,string,map,array,slice,pointer,struct(这里的one就属于struct),func//针对struct类获取其子字段名,特性,标签if otp.Kind()==reflect.Struct{//类型的检验是防止意外panic的必要预防之一,减少代码的不可预测性field_count:=otp.NumField()if field_count>0{var oftp reflect.StructFieldfor i:=0;i<field_count;i++{oftp=otp.Field(i)fmt.Println(oftp.Type.Kind(),oftp.Name,oftp.Tag)//走字段结构体输出才会拿到字段名和标签,reflect.Type拿到的名字是Kind()的go基本类型}}}
}

Elem()是reflect.Type和reflect.Value都存在的方法,它的作用为获取指针指向的本体,如果非指针使用此方法会造成panic
通过反射设置值

import ("fmt""reflect"
)func main(){//演示效果:将two的值设置到one上var(one stringtwo string="im two")otp:=reflect.TypeOf(one)ttp:=reflect.TypeOf(two)//假设我们不知道传入的两个参数的类型if otp==ttp{//适用于一切严格类型对比(非严格就是,你希望两个类型之间出现兼容性,特别是不同结构体之间的兼容,需要手动对比和赋值)ovl:=reflect.ValueOf(&one).Elem()//这里为了能使其修改必须是其指针,elem()导向本体过后便可对其操作tvl:=reflect.ValueOf(two)//单纯获得其值,并且这里不是指向two的指针,所以是不可修改的if ovl.CanSet(){//这个需为true,才能进行后续赋值,不检查这个,如果是你自己结构体字段首字母小写之类的导致不能赋值会造成panicovl.Set(tvl)//赋值fmt.Println(one)}       }
}

使用泛型进行限制
虽然两个参数都是类型不作限制,但是dst会被限制为任意类型的指针。这在[go 反射]之旅中能在输入参数上进行很大程度的优化,例如后续的反射拷贝(因为dst必须是指向你拷贝目标的指针才能对目标进行更改,而强制dst为指针也是变相提醒使用此函数的人,此处必须为指针)

func One[T any](dst *T,src any)error

一些可能会踩进去的小坑

  1. 反射未初始化的指针(var one *string,直接进行反射赋值会导致panic:invaild memory);解决方案:reflect.Value类型有一个方法IsNil,通过它先预判一遍,空的就返回,或者反射创建对象(后续go 反射 进阶会细说)
  2. 结构体字段首字母大小写:如果你结构体中某个字段不能canset,并且你valueof目标结构体的指针再elem进行canset,第一反应应该是检查大小写(大小写也是流畅控制是否暴露内部字段的重要技巧)
    现在你就学会了go 反射的基础技能了,能使用反射识别类型,和赋值。如果操练此文时遇见什么问题google也无解的,可私信我,一起学习交流交流
http://www.lryc.cn/news/220748.html

相关文章:

  • 【计算机网络】数据链路层-MAC和ARP协议
  • 本周三商店更新:多款套装下线,四款升级武器带异色皮肤返厂
  • WindowsServer2019-搭建FTP服务器
  • 国际阿里云服务器买哪种好用点?
  • 2023NOIP A层联测25 总结
  • Thread类的基本操作(JAVA多线程)
  • Redis 的三种部署模式
  • 【ArcGIS Pro二次开发】(73):使用NPOI库操作Excel
  • python获取电脑所连接的wifi密码
  • 动态壁纸软件Live Wallpaper HD mac中文版功能特色
  • Spring Boot 配置主从数据库实现读写分离
  • 【MongoDB】索引 - 单字段索引
  • 评估大型语言模型:综述
  • 设计模式之工厂模式(Factory)
  • 2023/11/6 JAVA学习
  • Android-JobService
  • GraphQL入门与开源的GraphQL引擎Hasura体验
  • Javascript知识点详解:this关键字的指向问题
  • 数据库的备份和恢复
  • DS图—图非0面积/bfs【数据结构】
  • Wnmp服务安装并结合内网穿透实现公网远程访问——“cpolar内网穿透”
  • 2023版Pycharm关闭一直显示closing project,正在关闭项目
  • Gradle笔记 二 Gradle的基础Groovy
  • 浅谈剩余电流动作继电器在电动伸缩门的应用
  • stable diffusion安装踩坑之clip安装、git报错
  • colmap gpu服务器安装
  • linux内的循环
  • 强化学习(RL)的学习笔记
  • 2023世界传感器大会开幕,汉威科技多领域创新产品引瞩目
  • 什么是机器学习中的正则化?