golang基础小记(21)——反射

反射是指在程序运行期间对程序本身进行访问和修改的能力。
反射的应用:当我们用空接口接收不同类型的结构体时,很难用类型断言去判断类型(因为自定义类型可以随意取名),这时就可以用到反射,来来得到结构体的类型,并进一步得到字段和对应值。
实际应用:json等数据解析(比如结构体博客中JSON序列化与反序列化)/ORM等工具
注意:

  • 反射引起的panic在编译时不会产生,只有在运行时才能发现,所以代码比较脆弱
  • 应用反射的代码通常难以理解
  • 反射的性能更低
    所以在写代码时要尽量避免使用反射,除非只能使用反射!(这也是我不想写细致内容的借口。。。以后用到再说。。。)

reflect包提供反射相关功能。

反射细致内容可以参考下面三个文档:

  1. 这篇博客对于反射的各种函数和使用方式讲的比较细致
  2. 这篇文章从应用出发循序渐进,更容易理解反射
  3. 标准库文档中文版,实际写代码时,对于各种方法/函数还是查文档更清晰一些,文档还推荐了一篇英文版的反射介绍

一些可能常用的方法

注意:所有值都默认用静态类型interface{}保存;只有用法,没有理由,具体可以查看参考中的标准库中文文档,或者代码实践。
该空接口类型变量名为data

判断data底层类型

// 判断data的底层类型是否是指针类型
if reflect.TypeOf(data).Kind() != reflect.Ptr {
	fmt.Println("data 不是指针类型")
}

其中Kind方法的返回值是Kind类型,reflect包中定义了很多Kind类型常量代表各种底层类型,Ptr就是其中一种。

获得指针指向的值的底层类型

reflect.TypeOf(data).Elem().Kind()

其中Elem方法返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map(Map类型的元素是值)、Ptr或Slice,会panic

获得结构体字段数量

此时data的底层类型是结构体。如果底层类型是指针,可以使用前面的Elem方法得到其值类型。

t := reflect.TypeOf(data)
num := t.NumField() // 此时num的值就是结构体字段数量

其中NumField方法返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic

获得结构体第i个字段的类型

t := reflect.TypeOf(data)
field := t.Field(0) // 返回的field是reflect.StructField类型
fieldName := field.Name // 得到字段名
fieldType := field.Type // 得到字段类型,返回值类型是reflect.Type
fieldTag := field.Tag // 得到字段的Tag,返回值类型是reflect.StructTag,该类型有Get(string) string方法,可以获得Tag中键对应的值

Field方法返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
Field方法一般和NumField方法在循环中使用。

根据字段名得到结构体的字段类型

假设structName是字段名

t := reflect.TypeOf(data)
structField, ok := t.FieldByName(structName)
if !ok {
	fmt.Println("字段名不存在")
	return
}
structObjType := structField.Type // 得到字段类型
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值