当前位置:首页 > 科技  > 软件

一篇学会Go中reflect反射的详细用法

来源: 责编: 时间:2024-05-11 09:21:05 318观看
导读应用场景1.判断函数变量是否否和标准2.验证接口值是否合理如(是否为空,传入的字段是否合规)3.获取变量的类型进行断言等操作在Go语言的反射机制中,任何接口值都由是一个具体类型和具体类型的值两部分组成的(我们在上一篇

应用场景

1.判断函数变量是否否和标准R6R28资讯网——每日最新资讯28at.com

2.验证接口值是否合理如(是否为空,传入的字段是否合规)R6R28资讯网——每日最新资讯28at.com

3.获取变量的类型进行断言等操作R6R28资讯网——每日最新资讯28at.com

在Go语言的反射机制中,任何接口值都由是一个具体类型和具体类型的值两部分组成的(我们在上一篇接口的博客中有介绍相关概念)。 在Go语言中反射的相关功能由内置的reflect包提供,任意接口值在反射中都可以理解为由reflect.Type和reflect.Value两部分组成,并且reflect包提供了reflect.TypeOf和reflect.ValueOf两个函数来获取任意对象的Value和Type。R6R28资讯网——每日最新资讯28at.com

1.结构体中使用反射

  • 获取 2 种类型信息的方法:

reflect.TypeOf() 获取类型信息,返回 Type 类型;R6R28资讯网——每日最新资讯28at.com

reflect.ValueOf() 获取数据信息,返回 Value 类型。R6R28资讯网——每日最新资讯28at.com

反射中值的可设置性,可以用 CanSet 方法来判断值是否可以设置。在 Go 中,函数参数的传递都是值拷贝,在反射中要修改值,必须传递指针,并且用 Elem() 方法获取指针的值,然后进行修改。
R6R28资讯网——每日最新资讯28at.com

reflect.ValueOf() 返回的 Value 类型:

  • 它有一个 Type() 方法,返回的是 reflect.Value 的 Type
  • 它有获取 Value 类型值的方法如果我们知道是 float 类型,所以直接用 Float() 方法。如果不知道具体类型呢?由上面例子可知用 Interface() 方法,然后在进行类型断言 v.Interface().(float64) 来判断获取值

v.Kind() 和 v.Type() 区别:

在 type MyInt int 里,v.Kind() 与 v.Type() 返回了不同的类型值,Kind()返回的是 int,Type() 返回的是 MyInt。在 Go 中,可以用 type 关键字定义自定义类型,Kind() 方法返回底层类型。比如还有结构体,指针等类型用 type 定义的,那么 Kind() 方法就可以获取这些类型的底层类型。R6R28资讯网——每日最新资讯28at.com

案例使用方法

package mainimport (	"fmt"	"reflect")type Userinfo struct {	Age      int `id:"iloveyou" num:"222"` //tag标签信息	UserName string}func GetReflickInfo(i interface{}) {	vl := reflect.ValueOf(i)	//nii := 200	fmt.Println("kind ======", vl.Kind())	if vl.Kind() == reflect.Ptr { //如是指针类型,先取值		vl = vl.Elem() //Elem方法就是取值操作	}	vlt := vl.Type() //获取具体类型,如自定义结构体的类型	fmt.Println("kind ======type===", vl.Kind(), vlt)	if vl.Kind() != reflect.Struct {		fmt.Println("类型:", vlt, " 名字:", vlt.Name(), " 数值:", vl)		//如是整数种类,又可以修改,CanSet属性为true,则进行修改。		if vl.Kind() == reflect.Int || vl.Kind() == reflect.Int64 && vl.CanSet() {			vl.SetInt(100)			//reflect.New(vlt)是创建了一个vlt类型的指针变量。			ni := reflect.New(vlt)			//创建后的ni是reflect.Value对象,需要通过ValueOf来赋值			ni = reflect.ValueOf(222)			fmt.Println("修改后int数值:", vl, "新建数值:", ni)		}		//如是浮点数种类,又可以修改,CanSet属性为true,则进行修改。		//可设置性检查:vl.CanSet() 是一个方法,用于确认vl的值是否可以被修改。在Go中,不是所有的反射值都能被设置,比如函数参数或者某些静态类型就不能。如果vl的值可以被改变,CanSet()将返回true。		if vl.Kind() == reflect.Float32 || vl.Kind() == reflect.Float64 && vl.CanSet() {			vl.SetFloat(100.11) //调用vl.SetFloat(100.11)方法将变量vl的值设置为100.11。			fmt.Println("修改后float数值:", vl)		}	} else {		fmt.Println("结构体类型:", vlt, " 名字:", vlt.Name())		for i := 0; i < vl.NumField(); i++ {			//vl是具体的值,这里vl.Field(i)就是枚举出每一个成员的值			//vlt是获取的类型,vlt.Field(i).Name和.Type是枚举出每一个成员的名字和类型			//也可以使用FieldByName,从指定的成员名获取具体值,vlret:= vl.FieldByName(vlt.Field(i).Name)			fmt.Println("成员名:", vlt.Field(i).Name, " 类型:", vlt.Field(i).Type, " 数值:", vl.Field(i))			//如是字符串种类,又可以修改,CanSet属性为true,则进行修改。			if vl.Field(i).Kind() == reflect.String && vl.Field(i).CanSet() {				vl.Field(i).SetString("new str")				fmt.Println("string成员修改后数值:", vl.Field(i))			}			//而tag标签信息都是静态的,无须实例化结构体,通过类型vlt可以获取到。			//这句vlt.Field(i).Tag.Lookup("id")就是枚举出每一个成员的tag标签,看里面是否有id这个key,并返回它的value值			if idtag, b := vlt.Field(i).Tag.Lookup("id"); b {				fmt.Println("tag id=", idtag)			}			if numtag, b := vlt.Field(i).Tag.Lookup("num"); b {				fmt.Println("tag num=", numtag)			}		}	}}func main() {	var price float64 = 3.14	var age int64 = 5	bd := Userinfo{100, "andy"}	ns := struct { //定义一个无名结构体		id   int		addr string	}{2, "aa"}	GetReflickInfo(price)	GetReflickInfo(&age) //把变量地址传递,所以可以修改。	GetReflickInfo(&bd)  //把结构体地址传递,所以可以修改。	fmt.Println(bd)      //打印出修改后的结构体变量	GetReflickInfo(ns)}


R6R28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-87989-0.html一篇学会Go中reflect反射的详细用法

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 深入理解分布式锁:原理、应用与挑战

下一篇: 一图看懂 React 源码中的同步更新逻辑

标签:
  • 热门焦点
  • 太卷!Redmi MAX 100英寸电视便宜了:12999元买Redmi史上最大屏

    8月5日消息,从小米商城了解到,Redmi MAX 100英寸巨屏电视日前迎来官方优惠,到手价12999元,比发布价便宜了7000元,在大屏电视市场开卷。据了解,Redmi MAX 100
  • 让我们一起聊聊文件的操作

    文件【1】文件是什么?文件是保存数据的地方,是数据源的一种,比如大家经常使用的word文档、txt文件、excel文件、jpg文件...都是文件。文件最主要的作用就是保存数据,它既可以保
  • 一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 重估百度丨“晚熟”的百度云,能等到春天吗?

    &copy;自象限原创作者|程心排版|王喻可2016年7月13日,百度云计算战略发布会在北京举行,宣告着百度智能云的正式启程。彼时的会场座无虚席,甚至排队排到了门外,在场的所有人几乎都
  • 得物宠物生意「狂飙」,发力“它经济”

    作者|花花小萌主近日,得物宣布正式上线宠物鉴别,通过得物App内的&ldquo;在线鉴别&rdquo;,可找到鉴别宠物的选项。通过上传自家宠物的部位细节,就能收获拥有专业资质认证的得物鉴
  • 2299元起!iQOO Pad明晚首销:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其最大的卖点
  • 苹果140W USB-C充电器:采用氮化镓技术

    据10 月 30 日 9to5 Mac 消息报道,当苹果推出新的 MacBook Pro 2021 时,该公司还推出了新的 140W USB-C 充电器,附赠在 MacBook Pro 16 英寸机型的盒子里,也支
  • 外交部:美方应停止在网络安全问题上不负责任地指责他国

      中国外交部今天(16日)举行例行记者会。会上,有记者问,美国情报官员称,他们正在阻拦来自中国以及其他国家的黑客获取相关科研成果。 中方对此有何评论?对此
Top