zoukankan      html  css  js  c++  java
  • reflect 反射

    反射:可以在运行时动态获取变量的相关信息

    导入 reflect 包

    reflect 包下主要是Type和Value 两个struct,

    • Type封装了“类型”的属性,定义相关的东西找他;
    • Value主要封装了“值”的属性,与值相关的东西找他没错。此外,他是线程安全的(或者叫goroutine安全)

    reflect包下主要有两个函数:

    • func TypeOf(i interface{}) Type获取变量的类型,返回reflect.Type类型 
    • func ValueOf(i interface{}) Value获取变量的值,返回reflect.Value类型 

    1. reflect.Value.Kind,获取变量的类别,返回⼀个常量 

    const (
    Invalid Kind = iota
    Bool
    Int
    Int8
    Int16
    Int32
    Int64
    Uint
    Uint8
    Uint16
    Uint32
    Uint64
    Uintptr
    Float32
    Float64
    Complex64
    Complex128
    Array
    Chan
    Func
    Interface
    Map
    Ptr
    Slice
    String
    Struct
    UnsafePointer
    )

    3.reflect.TypeOf

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func GetType(){
    	var i int
    	typeInfo := reflect.TypeOf(i)
    	fmt.Printf("%#v",typeInfo)
    	/*输出内容是:
    	&reflect.rtype{size:0x8, ptrdata:0x0, hash:0xf75371fa, tflag:0x7, 
    		align:0x8, fieldAlign:0x8, kind:0x82,
    		 alg:(*reflect.typeAlg)(0x53ca50), gcdata:(*uint8)(0x4d8d90), 
    		 str:1019, ptrToThis:44736}}
    rtype结构体
    type rtype struct {
    	size       uintptr
    	ptrdata    uintptr  // number of bytes in the type that can contain pointers
    	hash       uint32   // hash of type; avoids computation in hash tables
    	tflag      tflag    // extra type information flags
    	align      uint8    // alignment of variable with this type
    	fieldAlign uint8    // alignment of struct field with this type
    	kind       uint8    // enumeration for C
    	alg        *typeAlg // algorithm table
    	gcdata     *byte    // garbage collection data
    	str        nameOff  // string form
    	ptrToThis  typeOff  // type for pointer to this type, may be zero
    }
    */
    }
    func main(){
    	GetType()
    }
    

    4.获取变量的类型

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func GetType(a interface{}){  //获取变量类型
    	typeInfo := reflect.TypeOf(a)
    	kindof := typeInfo.Kind()
    	fmt.Printf("%v
    ",kindof)
    }
    type Student struct{
    	Name  string
    	Age   int
    }
    func main(){
    	var i int
    	var s Student
    	var c []string
    	var a [10]int
    	var p *int
    	GetType(i)   //int
    	GetType(s)   //struct
    	GetType(c)   //slice
    	GetType(a)   //array
    	GetType(p)   //ptr	
    }
    

    5.Type 类型的方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func GetType(a interface{}){  //获取变量类型
    	typeInfo := reflect.TypeOf(a)
    	kindof := typeInfo.Kind()
    	fmt.Printf("%v
    ",kindof)
    }
    func GetNmuberMethod(a interface{}){
    	typeInfo := reflect.TypeOf(a)
    	num_of_method := typeInfo.NumMethod()
    	fmt.Println(num_of_method)
    }
    type Student struct{
    	Name  string
    	Age   int
    }
    func(s *Student) SetName(name string){ //方法一
    	s.Name = name
    }
    func(s *Student) SetAge(age int){   //方法二
    	s.Age = age
    }
    func GetMethod(a interface{}){
    	typeInfo := reflect.TypeOf(a)
    	methodname,ok:= typeInfo.MethodByName("SetName")
    	if !ok {
    		fmt.Println("have no method name")
    	}else{
    		fmt.Println(methodname)
    	}
    
    
    }
    func main(){
    	var s Student
    	GetNmuberMethod(&s)  //2 ,获取s的方法
    	GetMethod(&s)        //typeInfo := reflect.TypeOf(a)
    }
    

      6.reflect.Value.Interface(),转换成interface{}类型

    变量 <------------>interface{}<------------------------->reflect.Value

    func GetValue(){
    	var i int =100
    	valueinfo := reflect.ValueOf(i)   //变量i 转成Value类开
    	tmp := valueinfo.Interface()      //value类型转成接口
    	val := tmp.(int)                  //接口转成int
    	fmt.Println(val)
         fmt.Println(valueinfo.Int()) //获取value类型的值。  } func main(){ GetValue() //100 }

      valueinfo.Type()      类型比如     Student

      valueinfo.Kind()      静态类型,struct

    7.利用反射来获取变量的值 

    reflect.ValueOf(x).Float()
    reflect.ValueOf(x).Int()
    reflect.ValueOf(x).String()
    reflect.ValueOf(x).Bool()

    8.通过反射来改变变量的值 

    reflect.Value.SetXX相关⽅法,⽐如:
    reflect.Value.SetFloat(),设置浮点数
    reflect.Value.SetInt(),设置整数
    reflect.Value.SetString(),设置字符串

    func main(){
    	var a float64
    	
    	// v :=reflect.ValueOf(a)  //这是一个值类型拷贝,修改不生效  panic: reflect: reflect.Value.SetFloat using unaddressable value
    	v :=reflect.ValueOf(&a)   //传入a的地址
    	// v.SetFloat(3.3)//引用类型赋值不能直接这样赋值 指针 赋值 :*地址=value  panic: reflect: reflect.Value.SetFloat using unaddressable value
    	v.Elem().SetFloat(3.3)  //反射中指针赋值 
    	fmt.Printf("%v
    ",a)//3.3
    

      其中v.Elem()⽤来获取指针指向的变量,相当于:
      var a *int;
      *a = 100

    9.⽤反射操作结构体

    a. reflect.Value.NumField()获取结构体中字段的个数
    b. reflect.Value.Method(n).Call来调⽤结构体中的⽅法

    获取个数:

    package main
    import (
    	"fmt"
    	"reflect"
    )
    type Student struct{
    	Name  string
    	Age   int
    	Sex   int
    }
    func(s *Student) Set(name string,age,sex int){ 
    	s.Name = name
    	s.Age = age
    	s.Sex = sex
    }
    func(s *Student) Getname(name  string){  
    	s.Name = name
    }
    func TestStruct(){
    	var s *Student = &Student{}
    	s.Set("www",18,1)
    	v := reflect.ValueOf(s)
    	num := v.Elem().NumField() //指针变量的字段数量
    	fmt.Println(num)   //3
    	sexinfo := v.Elem().FieldByName("Sex")  //获取字段信息
    	fmt.Println(sexinfo) //1
    	sexinfo.SetInt(100)
    	fmt.Println(s) //&{www 18 100}
    }
    func main(){
    	
    	TestStruct()    //3
    }
    

      调用结构体方法:

    type Student struct{
    	Name  string
    	Age   int
    	Sex   int
    }
    func(s *Student) Set(name string,age,sex int){ 
    	s.Name = name
    	s.Age = age
    	s.Sex = sex
    }
    func(s *Student) Getname(name  string){  
    	s.Name = name
    }
    
    func TestStruct_value(){
    	var s *Student = &Student{}
    	v := reflect.ValueOf(s)
    	setinfo := v.MethodByName("Set")
    	var par []reflect.Value
    	name := "wanghj"
    	age := 18
    	sex := 1
    	par = append(par,reflect.ValueOf(name))
    	par = append(par,reflect.ValueOf(age))
    	par = append(par,reflect.ValueOf(sex))
    	setinfo.Call(par)
    	fmt.Printf("%v
    ",s)
    }
    

      

  • 相关阅读:
    生成大小字母以及数字混乱的6位验证码
    重写吃货联盟
    集合练习:登录注册功能
    出现并解决Navicat 报错:1130-host ... is not allowed to connect to this MySql server,MySQL
    mysql在linux的安装
    Spring4分别整合mongo2.X和3.0
    oracle数据库使用plsql(64位)时出现的问题
    spring的CXF远程服务
    spring的定时任务或者说自动任务
    jquery节点查询
  • 原文地址:https://www.cnblogs.com/wanghaijun999/p/8489428.html
Copyright © 2011-2022 走看看