反射的基本使用

傷城~ 2021-07-24 19:34 529阅读 0赞

一 反射的使用场景——JSON序列化

1 代码

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type Monster struct {
  7. Name string `json:"monsterName"` // `json:"name"` 就是 struct tag
  8. Age int `json:"monsterAge"`
  9. Sal float64 `json:"monsterSal"`
  10. Sex string `json:"monsterSex"`
  11. }
  12. func main() {
  13. m := Monster{
  14. Name: "玉兔精",
  15. Age: 20,
  16. Sal: 888.76,
  17. Sex: "female",
  18. }
  19. data, _ := json.Marshal(m)
  20. fmt.Println("json result", string(data))
  21. }

2 测试

json result {“monsterName”:”玉兔精”,”monsterAge”:20,”monsterSal”:888.76,”monsterSex”:”female”}

3 分析

为什么序列化后,key-val 的 key 值是结构体 Tag 的值,而不是字段的名称。比如,不是 Name,而是 monsterName。这是因为底层使用到了反射。

二 反射的使用场景——函数的适配器和桥连接

1 代码

  1. package main
  2. import "fmt"
  3. func main() {
  4. // 定义一个匿名函数
  5. test1 := func(v1 int, v2 int) {
  6. fmt.Println(v1, v2)
  7. }
  8. // 定义另外一个匿名函数
  9. test2 := func(v1 int, v2 int, s string) {
  10. fmt.Println(v1, v2, s)
  11. }
  12. // 定义一个适配器函数,统一处理接口
  13. bridge := func(call interface{}, args ...interface{}) {
  14. fmt.Println("内容")
  15. }
  16. // 实现调用 test1 对应的函数
  17. bridge(test1, 1, 2)
  18. // 实现调用 test2 对应的函数
  19. bridge(test2, 1, 2, "求和")
  20. }

2 测试

内容

内容

3 分析

该适配器使用底层使用的便是反射

三 反射的基本介绍

1 基本介绍

a 反射可以在运行时动态获取变量的各种信息, 比如变量的类型(type),类别(kind)。

b 如果是结构体变量,还可以获取到结构体本身的信息:包括结构体的字段、 方法。

c 通过反射,可以修改变量的值,可以调用关联的方法。

d 使用反射,需要 import(“reflect”)

e 示意图

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70

2 反射的应用场景

a 不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数和方法反射。例如下面这种桥接模式。

func bridge(funcPtr interface{}, args …interface{})

第1个参数 funcPtr 以接口的形式传入函数指针,函数参数 args 以可变参数的形式传入,bridge 函数中可以用反射来动态执行 funcPtr 函数。

b 对结构体序列化时,如果结构体有指定 Tag,也会使用到反射生成对应的字符串。

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type Monster struct {
  7. Name string `json:"monsterName"` // `json:"name"` 就是 struct tag
  8. Age int `json:"monsterAge"`
  9. Sal float64 `json:"monsterSal"`
  10. Sex string `json:"monsterSex"`
  11. }
  12. func main() {
  13. m := Monster{
  14. Name: "玉兔精",
  15. Age: 20,
  16. Sal: 888.76,
  17. Sex: "female",
  18. }
  19. data, _ := json.Marshal(m)
  20. fmt.Println("json result", string(data))
  21. }

3 反射重要的函数和概念

a reflect.Type(变量名),获取变量的类型,返回 reflect.Type 类型。

b reflect.ValueOf(变量名),获取变量的值,返回 reflex.Value 类型。reflex.Value 是一个结构体类型,通过 reflex.Value 类型,可以获取到关于该变量的很多信息。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 1

c 变量、interface{} 和 reflect.Value 是可以相互转换的,这点在实际开发中,会经常使用到。示意图如下。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 2

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 3

发表评论

表情:
评论列表 (有 0 条评论,529人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用

    概述     JAVA反射机制是在运行中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态