反射

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

变量的内在机制

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

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

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

反射的使用

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

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

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

空接口和反射

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

反射获取interface类型信息

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

结构体与反射

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

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. Mysq索引优化(什么情况创建索引,什么情况不创建索引)

    一.以下情况需要创建索引 1.主键自动建立唯一索引 2.频繁作为查询条件的字段应该创建索引 3.查询中与其他表关联的字段,外键关系建立索引 4.单键/组合索引的选择问题,组合索引性价比更高 5.查询中 ...

  2. JS根据日期获取判断星期几

    /** * 根据日期字符串获取星期几 * @param dateString 日期字符串(如:2020-05-02) * @returns {String} */ function getWeek(d ...

  3. 【LeetCode】186. Reverse Words in a String II 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 每个单词单独翻转+总的翻转 日期 题目地址:https ...

  4. 【LeetCode】270. Closest Binary Search Tree Value 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetco ...

  5. 【LeetCode】951. Flip Equivalent Binary Trees 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...

  6. 【LeetCode】697. Degree of an Array 解题报告

    [LeetCode]697. Degree of an Array 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/degree- ...

  7. 【剑指Offer】52. 两个链表的第一个公共节点 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:栈 方法二:HashSet 方法三:不使用额外空间 日期 ...

  8. 汇编MMX实现图片淡入淡出核心代码

    计算机组成课程个人作业 参考: https://blog.csdn.net/yangjianqiao0/article/details/69388595 https://blog.csdn.net/d ...

  9. Gumbel distribution

    目录 概 主要内容 定义 Gumbel-Max trick Gumbel trick 用于归一化 代码 概 感觉这个分布的含义很有用啊, 能预测'最大', 也就是自然灾害, 太牛了. 主要内容 定义 ...

  10. Pytorch 图片载入

    目录 载入图片和坐标 Transforms Compose transforms 数据集的迭代 import os import torch import pandas as pd from skim ...