Go语言学习笔记十二(反射的类型对象)

Go语言的反射
在G语言程序中可以通过reflect包的TypeOf()函数获取任意值的类型对象,程序可以通过类型对象访问任意值的类型信息。

package main
import (
	"fmt"
	"reflect"
)
func main() {
	var a int 
	typeOfA := reflect.TypeOf(a)
	fmt.Printf("%v, %v",typeOfA.Name(),typeOfA.Kind())
}

这里定义一个int型变量
然后获取它的反射类型得到typeOfA对象
通过typeOfA的成员函数Name(),和Kind()获取变量的类型和种类

反射的类型和种类
在编程中使用最多的就是类型了,但是在反射中为了区分一个大的品种的类型时会使用到种类。例如需要统一判断类型中的指针时,使用种类(kind)信息可以方便一些。
种类指的是对象归属的品种
在reflect中有如下种类
const(
Invalid Kind iota //非法类型
Bool //布尔类型
Int //有符号整型
Int8 //有符号8位整型
Int16 //有符号16位整型
Int32 //有符号32位整型
Int64 //有符号64位整型
Uint //无符号整型
Uint8 //无符号8位整型
Uint16 //无符号16位整型
Uint32 //无符号32位整型
Uint64 //无符号64位整型
Uintptr //指针
Float32 //单精度浮点型
Float64 //双精度浮点型
Complex64 //64位复数类型
Complex128 //128位复数类型
Array //数组
Chan //通道
Func //函数
Interface //接口
Map //映射
Ptr //指针
Slice //切片
String //字符串
Struct //结构体
UnsafePointer //底层指针
)
Map,Slice ,Chan属于引用类型,使用起来类似于指针,但是在种类定义中仍然属于独立的种类,不属于指针。

从类型对象中获取类型名称和种类示例

package main
import (
	"fmt"
	"reflect"
)
//定义一个Enum类型
type Enum int 
const (
	Zero = 0
)
func main(){
	//声明一个空结构体
	type cat struct {
	}
	//获取结构体反射类型对象
	TypeOfCat := reflect.TypeOf(cat)
	//显示反射类型对象的类型和种类
	fmt.Printf("name: %v, kind: %v",TypeOfCat.Name(), TypeOfCat.Kind())
	//获取Zero常量的反射类型对象
	TypeOfA := reflect.TypeOf(Zero)
	//打印输出Zero反射类型的类型和种类
	fmt.Printf("Zero.name: %v, Zero.kind: %v",TypeOfA.Name(),TypeOfA.Kind())
}

以上代码实现对常量和结构体进行反射类型获取
声明了空结构体cat并对其实例化
使用reflect.TypeOf()获取实例化后cat的反射类型对象
然后输出cat的类型和种类
对常量Zero做同样操作

指针与指针指向的元素
Go程序对指针获取对象时,可以通过reflect.Elem()方法获取这个指针指向的元素类型,这个获取过程叫做取元素。等效于对指针做一个“*”操作。
取元素代码示例

package main
import (
	"fmt"
	"reflect"
)
func main() {
	type cat struct{
	
	}
	//实例化结构体
	ins := new(cat)
	//获取反射对象
	TypeOfCat := reflect.TypeOf(ins)
	//打印反射对象类型和种类
	fmt.Printf("name: '%v', kind: '%v'\n",TypeOfCat.Name(),TypeOfCat.Kind())
	//获取元素
	TypeOfCat := TypeOfCat.Elem()
	//显示反射类型对象的名称和种类
	fmt.Printf("name:'%v', kind: '%v'",TypeOfCat.Name(), TypeOfCat.Kind())
}		

以上代码中首先创建了一个cat的空结构体,这里ins是一个*cat类型的指针变量。获取反射对象后先输出一下对象的类型和种类,这里的输出结果为name: ’ ', kind: ‘ptr’
从输出结果可以看出来指针变量的类型名为空,种类为Ptr,Go程序中反射中对指针变量的所有种类都是Ptr
然后通过反射对象的内部函数Elem()获取元素
再进行打印指针变量指向元素的类型和种类
这里输出结果为name: ‘cat’, kind: ‘struct’
这里就能看到类型名为cat,种类为struct

使用反射获取结构体成员类型
任意值可以通过reflect.TypeOf()方法获取反射对象信息,如果它的类型是结构体,可以通过反射值对象(reflect.Type)的NumField()和Field()方法获取结构体成员的详细信息。
| 方法 |说明 |
|Field(i int) StructField|根据索引,返回索引对应的结构体字段信息。当值不是结构体或索引超界时发生宕机|
| NumField() int|返回结构体成员字段数量。当类型不是结构体或者索引超边界时引发宕机 |
|FieldByName(name string) (StructField,bool)| 根据给定字符串对应的结构体字段信息。没有找到时bool返回false,当类型不是结构体或者索引超界时发生宕机 |
|FieldByIndex(index []int) StructField|多层成员访问时,根据[]int提供的每个结构体的字段索引,返回字段信息,没有找到时返回零值。当类型不是结构体2或者索引超界时发生宕机|
|FieldByNameFunc(match func(string) bool) (StructField,bool)|根据匹配函数匹配需要的字段。当值不是结构体或索引超届时发生宕机 |

结构体字段类型
reflect.Type的Field()方法返回StructField结构,这个结构描述结构体的成员信息,通过这个信息可以获取成员与结构体的关系,如偏移量、索引、是否为匿名字段,结构体标签(Struct Tag)等,而且还可以通过StructField的Type字段进一步获取结构体成员的类型信息。
StructField的结构为

type StructField struct {
	Name string            //字段名
	PkgPath string         //字段路径
	Tag StructTag          //字段的结构体标签
	Type Type              //字段反射类型对象
	Offset uintptr         //字段在结构体中相对偏移
	Index []int            //Type.FieldByIndex中的返回的索引值
	Anonymous bool         //是否为匿名字段
}

获取成员反射信息代码示例

package main
import (
	"fmt"
	"reflect"
)
func main() {
	//声明一个结构体
	type cat struct {
		Name string
		//带有结构体标签的字段
		Type int 'json:"type" id:"100"'
	}
	//创建cat实例
	ins := cat{Name:"hzc",Type:1}
	//获取结构体实例的反射类型
	TypeOfCat := reflect.TypeOf(ins)
	//遍历结构体所有成员
	for i := 0; i < TypeOfCat.Numfield(); i++ {
		//获取每个成员的结构体字段类型
		typeOf := TypeOfCat.Field(i)
		//输出成员名和tag
		fmt.Printf("name: '%v', tag: '%v'\n",typeOf.Name,typeOf.Tag)
		//通过字段名找到字段类型信息
		if catType, ok := TypeOfCat.FieldByName("Type"); ok {
			//从tag中取出需要的tag
			fmt.Println(catType.Tag.Get("json"),catType.Tag.Get("id"))
		}
	}
}

以上代码实例化一个结构体并遍历其成员,再通过 reflect.Type的FieldBtName()方法查找结构体中指定名称的字段,直接获取信息。

结构体标签(StructTag)–对结构体字段的额外信息标签
通过reflect.Type获取结构体成员信息reflect.StructField结构中的Tag被称为结构体标签(Struct Tag)
结构体标签的格式
key1:“value1” key2:“value2”
结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔。
从结构体标签中获取值
func (tag StructTag)Get(key string) string{}
根据tag中的键获取对应的值,例如’key1:“value1” key2:“value2”‘的Tag中,可以传入"key1"获得"value1"
func (tag StructTag) LookUp(key string) (value string, ok bool){}
根据键查询值是否存在,存在则返回值ok返回true,不存在则值返回空ok返回false。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值