反射

反射是指程序在运行期对程序本身访问和修改的能力

变量的内在机制

变量包含类型信息和值信息 var arr [10]int arr[0] = 10

类型信息:是静态的元信息,是预先定义好的

值信息:是程序运行过程中动态改变的

反射的使用

reflect包封装了反射相关的方法

获取类型信息:reflect.TypeOf,是静态的

获取值信息:reflect.ValueOf,是动态的

空接口和反射

反射可以在运行时动态获取程序的各种详细信息

反射获取interface类型信息

  1. 反射获取interface类型信息
func main() {
var x = math.Pi
reflectType(x)
} func reflectType(tmp interface{}) {
t := reflect.TypeOf(tmp)
fmt.Println("类型是:", t) // Kind()可以获取具体类型
k := t.Kind()
fmt.Println(k) switch k {
case reflect.Float64:
fmt.Println("Float64类型")
case reflect.String:
fmt.Println("String类型")
} }
  1. 反射获取interface的值信息
func main() {
var x = math.Pi
reflectValue(x)
} func reflectValue(tmp interface{}) {
fmt.Printf("%v: %T\n", tmp, tmp)
v := reflect.ValueOf(tmp)
fmt.Println(v) // 获取到v的具体类型
k := v.Kind()
fmt.Println(k) switch k {
case reflect.Float64:
fmt.Println("float64类型")
}
}
  1. 反射修改值信息
func main() {
var x = math.Pi
// 反射修改值需要传递指针类型,不是float类型
reflectSetValue(&x)
fmt.Println("main: ", x)
} func reflectSetValue(tmp interface{}) {
v := reflect.ValueOf(tmp)
k := v.Kind() // Kind() 获取具体类型
switch k {
case reflect.Float64:
// 反射修改值
v.SetFloat(15)
fmt.Println("tmp is", v.Float())
case reflect.Ptr:
// Elem获取地址指向的值
v.Elem().SetFloat(18)
fmt.Println("tmp is", v.Elem().Float())
fmt.Println(v.Pointer())
}
}

结构体与反射

  1. 查看类型、字段和方法
点击查看代码
type User struct {
Id int
Name string
Age int
}
func (u User) Hello() {
fmt.Println("Hello")
} func main() {
u := User{11, "zhang", 18}
Poni(u)
} func Poni(o interface{}) {
t := reflect.TypeOf(o)
fmt.Println("类型是:", t) // 类型是: main.User
fmt.Println(t.Name()) // User v := reflect.ValueOf(o)
fmt.Println("值是:", v) // 值是: {11 zhang 18} // 获取所有属性
// t.NumField 可以获取字段数量
for i := 0; i < t.NumField(); i++ {
// 获取每个字段
f := t.Field(i)
fmt.Println(f.Name, f.Type) // 获取字段的值信息
val := v.Field(i).Interface() // Interface()获取字段对应的值
fmt.Println(val)
} fmt.Println("==========方法===========")
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Println(m.Name, m.Type)
}
}
  1. 查看匿名字段
点击查看代码
type User struct {
Id int
Name string
Age int
}
type Boy struct {
User
Addr string
} func main() {
b := Boy{User{11, "zhang", 18}, "北京市"}
t := reflect.TypeOf(b)
fmt.Println(t) // main.Boy // 匿名:Anonymous
fmt.Printf("%#v\n", t.Field(0))
// 输出:reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x3de280), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true} // 值信息
fmt.Printf("%#v\n", reflect.ValueOf(b).Field(0))
}
  1. 修改结构体的值
点击查看代码
type User struct {
Id int
Name string
Age int
} func main() {
u := User{11, "zhang", 18}
setValue(&u)
fmt.Println("main:", u)
} // 修改结构体指向的值
func setValue(o interface{}) {
v := reflect.ValueOf(o)
// 获取指针指向的元素
v = v.Elem()
// 获取字段
f := v.FieldByName("Name")
if f.Kind() == reflect.String {
f.SetString("哈哈哈")
}
}
  1. 调用方法
点击查看代码
type User struct {
Id int
Name string
Age int
}
func (User) Hello(name string) {
fmt.Println("hello: ", name)
} func main() {
u := User{11, "lisi", 88}
v := reflect.ValueOf(u)
// 获取方法
m := v.MethodByName("Hello")
// 构建一些参数
args := []reflect.Value{reflect.ValueOf("6666")}
// 没参数的情况下:var args2 []reflect.Value
// 调用方法,需要传入方法的参数
m.Call(args)
}
  1. 获取字段的tag
type Student struct {
Name string `json:"name1" db:"name2"`
} func main() {
s := Student{Name: "lisi"}
v := reflect.ValueOf(&s)
// 注意:如果使用结构体指针,t.Elem()需要获取指针对应的值,如果使用的是s结构体,那么不需要t.Elem(),直接t.Field即可
// 类型
t := v.Type()
// 获取字段
f := t.Elem().Field(0)
fmt.Println(f.Tag.Get("json"))
fmt.Println(f.Tag.Get("db"))
}

golang中的标准库反射的更多相关文章

  1. golang中的标准库数据格式

    数据格式介绍 是系统中数据交互不可缺少的内容 这里主要介绍JSON.XML.MSGPack JSON json是完全独立于语言的文本格式,是k-v的形式 name:zs 应用场景:前后端交互,系统间数 ...

  2. golang中的标准库context

    在 Go http包的Server中,每一个请求在都有一个对应的 goroutine 去处理.请求处理函数通常会启动额外的 goroutine 用来访问后端服务,比如数据库和RPC服务.用来处理一个请 ...

  3. golang中的标准库log

    Go语言内置的log包实现了简单的日志服务.本文介绍了标准库log的基本使用. 使用Logger log包定义了Logger类型,该类型提供了一些格式化输出的方法.本包也提供了一个预定义的" ...

  4. golang中的标准库context解读

    简介 golang 中的创建一个新的 goroutine , 并不会返回像c语言类似的pid,所有我们不能从外部杀死某个goroutine,所有我就得让它自己结束,之前我们用 channel + se ...

  5. golang中的标准库http

    Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现. http客户端 基本的HTTP/HTTPS请求 Get.Head.Post和PostForm函数发出HTTP/HTTP ...

  6. golang中的标准库template

    html/template包实现了数据驱动的模板,用于生成可对抗代码注入的安全HTML输出.它提供了和text/template包相同的接口,Go语言中输出HTML的场景都应使用text/templa ...

  7. golang中的标准库IO操作

    参考链接 输入输出的底层原理 终端其实是一个文件,相关实例如下: os.Stdin:标准输入的文件实例,类型为*File os.Stdout:标准输出的文件实例,类型为*File os.Stderr: ...

  8. golang中的标准库time

    时间类型 time.Time类型表示时间.我们可以通过time.Now()函数获取当前的时间对象,然后获取时间对象的年月日时分秒等信息.示例代码如下: func main() { current := ...

  9. golang中的标准库strconv

    strconv 包 strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数: Atoi().Itia().parse系列.format系列.append系列. string与int ...

随机推荐

  1. centos使用docker安装redis ,并设置外网访问

    拉取镜像 docker pull redis:4.0 在主机/data/redis/conf目录下新建redis.conf文件vim /data/redis/conf/redis.conf # Red ...

  2. JAVA实现office文档(word、excel、ppt等)、压缩包在线预览,支持禁止下载功能、支持PC和手机

    我们使用的是永中的第三方服务.支持直接转换文档的线上地址,也可以直接把文档上传到官方服务器上 官方文档地址:https://www.yozodcs.com/page/help.html#link152 ...

  3. JAVA获取访问者的内网IP地址

    /** * 获取访问者内网IP * @return the server ip */ public static String getIntranetIp() { // 本地IP,如果没有配置外网IP ...

  4. VS2013 or up version +常用插件

    !!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 下载地址: https://github.com/mohistH/vs2013_extens ...

  5. 【九度OJ】题目1192:回文字符串 解题报告

    [九度OJ]题目1192:回文字符串 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1192 题目描述: 给出一个长度不超过1000的 ...

  6. DevTools 实现原理与性能分析实战

    一.引言 从 2008 年 Google 释放出第一版的 Chrome 后,整个 Web 开发领域仿佛被注入了一股新鲜血液,渐渐打破了 IE 一家独大的时代.Chrome 和 Firefox 是 W3 ...

  7. IM2603资料 Type-C 扩展坞电源管理芯片

    用于带有集成降压转换器的 Type-C 外围应用的电源管理 IC IM2603 是一款主要用于 Type-C 外围应用的电源管理 IC. 它集成了一个带有内置高侧 MOSFET 的同步降压转换器和一个 ...

  8. spring练习,使用Eclipse搭建的Spring开发环境,属性注入通过构造方法方式实现,模拟用户的正常登录。

    相关 知识 >>> 相关 练习 >>> 实现要求: 使用Eclipse搭建的Spring开发环境,属性注入通过构造方法方式实现,模拟用户的正常登录.要求如下: 通过 ...

  9. LDAP客户端安装

    安装环境: 10.43.159.7 客户端 使用ldap客户端验证登陆: 用户为10.43.159.9服务端上面创建的ldap:zdh1234 1.安装LDAP client认证需要的pam包 yum ...

  10. 微信小程序--数据共享与方法共享

    目录 全局数据共享 Mobox npm安装及其注意事项 小程序对 npm 的支持与限制 npm 依赖包的安装与使用 Mobox 1. 全局数据共享 2. 小程序中的全局数据共享方案 3. 使用mobx ...