Go 反射包使用教程

Wesley13
• 阅读 667

引子

几乎所有高级语言都有反射功能,以用于语言的灵活性,实现各种封装。

Java(java.lang.reflect):

//获得Person的Class对象
Class<?> cls = testJavaSE.Person.class;//Class.forName("testJavaSE.Person");
//创建Person实例
Person p = (Person)cls.newInstance();
//获得Person的Method对象,参数为方法名,参数列表的类型Class对象
Method method = cls.getMethod("eat",String.class);
//invoke方法,参数为Person实例对象,和想要调用的方法参数
String value = (String)method.invoke(p,"肉");
//输出invoke方法的返回值
System.out.println(value);

Php(Reflection)

$reflect = new \\ReflectionClass();  
if($reflect->hasMethod("eat")) {  
  echo $reflect->getMethod("eat")->invoke($reflect->newInstance(), "php");
}

可以看到,我们可以很容易实现灵活的功能。那么go作为一门语法约束较为严格的语言,如果不支持反射的话,真的会很难大规模普及,所以官方还是提供了一个灵活的反射包(ps: 虽然不太好用)

go 反射包

go反射包是存在与内核里面的

GOROOT/src/reflect/*

这里要说明一点,go不是一门纯正的面向对象语言,所以反射包的涉及也略有不同。

反射由reflect包提供支持,主要方法:

  • func TypeOf ( i interface{} ) Type:

如 reflect.Typeof(x) ,形参x被保存为一个接口值并作为参数传递(复制),方法内部会把该接口值拆包恢复出x的类型信息保存为reflect.Type并返回

  • func ValueOf ( i interface{} ) Value:

如 reflect.ValueOf(x) ,形参被保存为一个接口值并作为参数传递(复制), 方法内部把该接口值的值恢复出来保存为reflect.Value并返回;

type

Type 接口:可以表示一个Go类型

Kind()将返回一个常量,表示具体类型的底层类型

Elem()方法返回指针、数组、切片、map、通道的基类型;

可用反射提取struct tag,还能自动分解,常用于ORM映射、数据验证等;

辅助判断方法Implements()、ConvertibleTo()、AssignableTo()

example(判断一个结构体是否包含某个属性):

t := reflect.TypeOf(s)
if _, ok := t.FieldByName("Name"); ok {
   return true
}
return false

value

Value 结构体:可以持有一个任意类型的值

调用 Value 的 Type() 将返回具体类型所对应的 reflect.Type(静态类型)
调用 Value 的 Kind() 将返回一个常量,表示具体类型的底层类型
Interface方法是ValueOf方法的逆,它把一个reflect.Value恢复成一个接口值,把Value中保存的类型和值的信息打包成一个接口表示并返回:
通道类型的反射对象:有TrySend()、TryRecv()方法
IsNil()方法判断反射对象保存的值是否为nil

example(反射一个普通的数值):

var x int64 = 0
func getInterfaceValueInt64(x interface{}) int64 {
    //这里基础类型已经实现了封装
    //i64 := reflect.ValueOf(x).Int()
    i64 :=  reflect.ValueOf(x).(int64)
}
d: =getInterfaceValueInt64(x)
fmt.Println(d)

那么复杂类型如何处理呢?继续代码举例吧:

example(array or slice):

func SliceBuildWithInterface(v interface{}) reflect.Value {  
   typ := reflect.TypeOf(v) // 获取类型
   sliceValue := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)//生成value对象

   slice := reflect.New(sliceValue.Type()) //构建切片
   slice.Elem().Set(sliceValue) //设置切片值

   return slice
}

为什么需要反射呢?

  • 功能更强大
  • 更安全,防止直接调用没有暴露的内部方法
  • 可维护,直接写字符串是硬编码
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java爬虫之JSoup使用教程
title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这