Go语言之反射

变量与反射

1.变量的内在机制

A.类型信息,这部分是元信息,是预先定义好的,比如

  1: var arr [10]int
  2: arr[0] = 10
  3: arr[1] = 20
  4: arr[2] = 30
  5: arr[3] = 40
  6: arr[4] = 50

B.值类型,这部分是程序运行过程中,动态改变的.

  1: type Animal struct {
  2:     Name string
  3:     age int
  4: }
  5: 
  6: var a Animal

2.反射与空接口

A. 空接口可以存储任何类型的变量

B.那么给你一个空接口,怎么知道里面存储的是什么东西

c.在运行时动态的获取一个变量的类型信息和值类型,就叫反射

3.怎么分析

A.内置包 reflect

B.获取类型信息:reflect.TypeOf

C:获取值信息 reflect.ValueOf

基本数据类型分析(a是一个空接口变量)

  1: package main
  2: 
  3: import (
  4:     "fmt"
  5:     "reflect"
  6: )
  7: 
  8: func reflect_example(a interface{}) {
  9:     t := reflect.TypeOf(a)
 10:     fmt.Printf("type of a: %v\n", t)
 11: }
 12: 
 13: func main() {
 14:     var x float64 = 3.4
 15:     reflect_example(x)
 16:     var y float32 = 3.2
 17:     reflect_example(y)
 18: }
打印
  1: type of a: float64
  2: type of a: float32

t.Kind()直接获取类型,结果为reflect.Int64,reflect.String等…可以用swtich来判断

reflect.ValueOf获取变量的值相关信息:

  1: var x float64 = 3.4
  2: v := reflect.ValueOf(x)
  3: // 和reflect.TypeOf功能是一样的
  4: fmt.Println("type:", v.Type())
  5: fmt.Println("kind is float64:", v.kind()==reflect.Float64)
  6: 
  7: fmt.Println("value:", v.Float())

通过反射设置变量的值

  1: func reflect_set_value(a interface{}){
  2:     t := reflect.ValueOf(a)
  3:     k := t.Kind()
  4:     switch k {
  5:     case reflect.Int64:
  6:             t.SetInt(100)
  7:             fmt.Println("typeof is int64")
  8:     case reflect.Float64:
  9:             t.SetFloat(6.6)
 10:             fmt.Println("typeof is Float64")
 11:     case reflect.Ptr:
 12:             //t.Elem()等同于*t
 13:             t.Elem().SetFloat(6.6)
 14:     }
 15: }
 16: func main() {
 17:     var x float64 = 9.9
 18:     // 注意这里传入的是x的指针
 19:     reflect_set_value(&x)
 20:     fmt.Println("x value:",x)
 21: }

结构体反射

获取结构体类型相关信息

  1: type student struct {
  2:     Name string
  3:     Sex int
  4:     Age int
  5: }
  6: func main()  {
  7:     var a student
  8:     v := reflect.ValueOf(a)
  9:     t := v.Type()
 10:     // t := reflect.TypeOf(a)
 11:     kind := t.Kind()
 12:     switch kind {
 13:     case reflect.Int64:
 14:             fmt.Println("")
 15:     case reflect.Float64:
 16:             fmt.Println("")
 17:     case reflect.Struct:
 18:             fmt.Println("is struct")
 19:             fmt.Println("field num", v.NumField())
 20:             for i:=0;i<v.NumField();i++ {
 21:                     field := v.Field(i)
 22:                     fmt.Printf("name-%s, type-%v value-%v\n", t.Field(i).Name, field.Type(), field.Interface())
 23:             }
 24:     }

设置结构体字段的值

  1: func main()  {
  2:     var a student
  3:     v := reflect.ValueOf(&a)
  4:     v.Elem().Field(0).SetString("stu01")
  5:     v.Elem().FieldByName("Sex").SetInt(2)
  6:     v.Elem().FieldByName("Age").SetInt(18)
  7:     fmt.Println("a:", a)

结构体方法调用

  1: type Student struct {
  2:     Name string
  3:     Sex int
  4:     Age int
  5: }
  6: func (s *Student) SetName(name string)  {
  7:     s.Name = name
  8: }
  9: func (s *Student) Print() {
 10:     fmt.Println(s.Name)
 11: }
 12: func main()  {
 13:     var a Student
 14:     v := reflect.ValueOf(&a)
 15:     t := v.Type()
 16:     
 17:     // 获取方法的具体信息
 18:     fmt.Println("method numbers", t.NumMethod())
 19:     for i:=0; i<t.NumMethod();i++ {
 20:             method := t.Method(i)
 21:             fmt.Printf("name:%s type:%s\n", method.Name, method.Type)
 22:     }
 23:     // 有参数的方法
 24:     m := v.MethodByName("SetName")
 25:     var arg1 []reflect.Value
 26:     name := "stu1"
 27:     // 将string转化成reflect.Value类型
 28:     nameVal := reflect.ValueOf(name)
 29:     arg1 = append(arg1, nameVal)
 30:     m.Call(arg1)
 31: 
 32:     // 无参数的方法
 33:     m1 := v.MethodByName("Print")
 34:     var arg2 []reflect.Value
 35:     m1.Call(arg2)

结果

  1: method numbers 2
  2: name:Print type:func(*main.Student)
  3: name:SetName type:func(*main.Student, string)
  4: stu1

tag信息获取

  1: type Student struct {
  2:     Name string `json:"name"`
  3: }
  4: 
  5: func main()  {
  6:     var a Student
  7:     v := reflect.ValueOf(&a)
  8:     t := v.Type()
  9:     field0 := t.Elem().Field(0)
 10:     fmt.Println("tag json =",field0.Tag.Get("json"))
 11: }

总结

反射就是在运行程序中可以动态地获取一个变量的类型信息和值信息