go Language Series - reflection

reflection

  1. Reflection can acquire various information dynamically at runtime variables, variables such as the type (type), category (kind)

  2. If the variable is a structure, the structure may also obtain the information of itself (including the field structure, method)

  3. By reflection, you can modify the value of the variable to be associated with the call method

  4. Using reflection, requires import ( "reflect")

Lead reflection

import (
   "encoding/json"
   "fmt"
)
type Monster struct {
   Name string `json:"monsterName"`
   Age int `json:"monsterAge"`
   Sal float64 `json:"monsterSal"`
   Sex string `json:"monsterSex"`
}
func main()  {
   m := Monster{
      Name : "玉兔精",
      Age : 20,
      Sal : 888.99,
      Sex : "female",
   }
   data,_ := json.Marshal(m)
   fmt.Println("json result:", string(data))
}

Output : json result: { "monsterName" : " rabbit fine", "monsterAge": 20, "monsterSal": 888.99, "monsterSex": "female"} thinking: Why

Thinking :

Why serialization, key - key value val is the value of Tag structure, rather than the name of the field, such as: Name but not: "monsterName": "rabbit fine"

Lead reflection

Using reflection, prepared by the adapter function, bridge

Reflected scenarios

Reflecting There are two common scenarios

  1. Interface call does not know which function to identify specific interface call parameters at run time based on the incoming, reflected this need for a method or function. This bridging problems such as the following models, such previously proposed
func bridge(funcPtr interface{}, args ...interface{})

The first parameter passed to the function pointers funcPtr interface in the form, in the form of function parameters passed args variable parameter, Bridge function may be performed dynamically funcPtr reflection function

  1. When the structure of the serialization, if the structure has designated the Tag, the reflection is also used to generate the corresponding character string
type Monster struct {
   Name string `json:"monsterName"`
   Age int `json:"monsterAge"`
   Sal float64 `json:"monsterSal"`
   Sex string `json:"monsterSex"`
}

Reflecting important functions and concepts

  1. reflect.TypeOf (variable name), acquired type of the variable, return type reflect.Type

  2. reflect.ValueOf (variable name), obtaining the value of the variable, return type reflect.Value reflect.Value is a structure type. By reflect.Value, you can obtain a lot of information about the variable

    3) variable, interface {} and reflect.Value can be converted to each other, this in actual development, will be frequently used. Draw schematic

Reflected Getting Started

Write a case of presentation (structure, basic data types, interface {}, reflect.Value) to perform basic operations reflected code demonstrates

import (
   "fmt"
   "reflect"
)
//专门演示反射
func reflectTest01(b interface{}) {
   //通过反射获取的传入的变量的type,kind,值
   //1. 先获取到reflect.Type
   rTyp := reflect.TypeOf(b)
   fmt.Println("rTyp = ", rTyp)
   //2. 获取到reflect.Vakue
   rVal := reflect.ValueOf(b)
   n2 := 2 + rVal.Int()
   fmt.Println("n2 = ", n2)
   fmt.Printf("rVal = %v rVal type = %T\n", rVal, rVal)
   //下面将rVal 转成interface{}
   iV := rVal.Interface()
   //将interface{}通过断言转成需要的类型
   num2 := iV.(int)
   fmt.Println("num2 = ", num2)
}
//专门演示反射[对结构体的反射]
func reflectTest02(b interface{})  {
   //通过反射获取传入的变量的type,kind,值
   //1. 先获取到reflect.Type
   rTyp := reflect.TypeOf(b)
   fmt.Println("rTyp = ", rTyp)
   //2. 获取到reflect.Value
   rVal := reflect.ValueOf(b)

   //下面将rVal转成interface{}
   iV := rVal.Interface()
   fmt.Printf("iv = %v iv type = %T\n", iV, iV)
   //将interface{}通过断言转成需要的类型
   //这里,简单使用到检测的类型断言
   //也可以使用switch的断言形式来做的更加的灵活
   stu, ok := iV.(Student)
   if ok {
      fmt.Printf("stu.Name = %v\n", stu.Name)
   }
}

type Student struct {
   Name string
   Age int
}
type Monster struct {
   Name string
   Age int
}

func main()  {
   //演示对(结构体、基本数据类型、interface{}、reflect.Value)进行反射的基本操作
   //1. 先定义一个int
   var num int = 100
   reflectTest01(num)

   //2. 定义一个Student的实例
   stu := Student{
      Name : "tom",
      Age : 20,
   }
   reflectTest02(stu)
}
//rTyp =  int
//n2 =  102
//rVal = 100 rVal type = reflect.Value
//num2 =  100
//rTyp =  main.Student
//iv = {tom 20} iv type = main.Student
//stu.Name = tom

Notes and reflections details

1) reflect.Value.Kind category obtaining variable, returns a constant

difference 2) Type of Kind and

Type is the type, is Kind category, Type and Kind may be the same, it may be different

For example: var num int = 10 num is the Type int, Kind is int

For example: var stu Student stu of Type is pKg1.Student, Kind is a struct

  1. By allowing the reflection variable switches between the interface {} and Reflect.Value, this painted schematic and explain over the quick start in front of the case, where the look of how code embodied
  2. Use reflection to obtain the value of the variable (and the corresponding return type) required to match the data type, such as x is int, then you should use reflect.Value (x) .Int (), but not the other, or reported panic
  3. Variable is modified by reflection, note that when using the method to set the desired SetXxx be accomplished by a corresponding pointer type, so as to change the value of the variable passed, while required to reflect.Value.Elem () method
import (
   "fmt"
   "reflect"
)

func testInt(b interface{})  {
   val := reflect.ValueOf(b)
   fmt.Printf("val type = %T\n", val)
   val.Elem().SetInt(110)
   fmt.Printf("val = %v\n", val)
}
func main()  {
   var num int = 20
   testInt(&num)
   fmt.Println("num = ", num)
}
//val type = reflect.Value
//val = 0xc000054080
//num =  110
  1. reflect.Valut.Elem () should understand how

Reflective practice

  1. To a variable var v float64 = 1.2, using the reflection upon its reflect.Value, then acquires the corresponding Type, Kind and value, and converts into reflect.Value interface {}, then the interface {} is converted into float64

  2. See sections of the code to determine whether proper, why

import (
   "fmt"
   "reflect"
)

func main()  {
   var str string = "tom" // ok
   fs := reflect.ValueOf(&str) // ok fs -> string
   //fs.SetString("jack")  //error
   fs.Elem().SetString("jack")
   fmt.Printf("%v\n", str)
}
//jack

Reflecting best practices

  1. Using reflection to traverse the field structure, the structure of the method call, and acquires the value of the tag structure
import (
   "fmt"
   "reflect"
)
//定义一个Monster结构体
type Monster struct {
   Name  string `json:"name"`
   Age int `json:"monster_age"`
   Score float32 `json:"成绩"`
   Sex string
}
//方法,返回两个数的和
func (s Monster) GetSum(n1, n2 int) int {
   return n1 + n2
}
//方法,接收四个值,给s赋值
func (s Monster) Set(name string, age int, score float32, sex string) {
   s.Name = name
   s.Age = age
   s.Score = score
   s.Sex = sex
}
//方法,显示s的值
func (s Monster) Print() {
   fmt.Println("---start---")
   fmt.Println(s)
   fmt.Println("---end---")
}
func TestStruct(a interface{})  {
   //获取reflect.Type类型
   typ := reflect.TypeOf(a)
   //获取reflect.Value类型
   val := reflect.ValueOf(a)
   //获取到a对应的类别
   kd := val.Kind()
   //如果传入的不是struct,就退出
   if kd != reflect.Struct {
      fmt.Println("expect struct")
      return
   }
   //获取到该结构体有几个字段
   num := val.NumField()
   fmt.Printf("struct has %d fields \n", num) //4
   //变量结构体的所有字段
   for i := 0; i < num; i++ {
      fmt.Printf("Field %d: 值为=%v\n", i, val.Field(i))
      //获取到struct标签,注意需要通过reflect.Type来获取tag标签的值
      tagVal := typ.Field(i).Tag.Get("json")
      //如果该字段于tag标签就显示,否则就不显示
      if tagVal != "" {
         fmt.Printf("Field %d: tag 为 = %v\n", i, tagVal)
      }
   }
   //获取到该结构体有多少个方法
   numOfMethod := val.NumMethod()
   fmt.Printf("struct has %d methods \n", numOfMethod)
   //var params []reflect.Value
   //方法的排序默认是按照函数名的排序(ASCII码)
   val.Method(1).Call(nil)//获取到第二个方法,调用它

   //调用结构体的第1个方法Method(0)
   var params []reflect.Value //声明了[]reflect.Value
   params = append(params, reflect.ValueOf(10))
   params = append(params, reflect.ValueOf(40))
   res := val.Method(0).Call(params) // 传入的参数是[]reflect.Value ,返回[]reflect.Value
   fmt.Println("res = ", res[0].Int()) //返回结果,返回的结果是[]reflect.Value
}
func main()  {
   //创建了一个Monster实例
   var a Monster = Monster{
      Name: "黄鼠狼精",
      Age: 400,
      Score: 30.8,
   }
   //将Monster实例传递给TestStruct函数
   TestStruct(a)
}
//struct has 4 fields 
//Field 0: 值为=黄鼠狼精
//Field 0: tag 为 = name
//Field 1: 值为=400
//Field 1: tag 为 = monster_age
//Field 2: 值为=30.8
//Field 2: tag 为 = 成绩
//Field 3: 值为=
//struct has 3 methods 
//---start---
//{黄鼠狼精 400 30.8 }
//---end---
//res =  50
  1. Use to get to tag reflection structure, the value of the traverse field, modify the field value, the method calls the structure (requirement: by way of the delivery address is completed, can be modified on the front case)

  2. Defines two functions test1 and test2, define a unitary adapter function as an interface

  3. Reflection operation using any type of structure

  4. Using reflection to create and manipulate the structure

  5. Cal preparation of a structure, and there are two fields Num1 Num2

  6. Method GetSub (name string)

  7. All information fields reflecting structure traversal Cal

  8. Uses reflection complete the call, is output in the form of GetSub "Tom completed subtraction, 8--3 = 5"

Guess you like

Origin www.cnblogs.com/zisefeizhu/p/12643858.html