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\n",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\n",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\n",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\n",s)
}

  

 

posted @ 2018-03-01 17:11  whj999  阅读(284)  评论(0编辑  收藏  举报