zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", 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: }

    总结

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

  • 相关阅读:
    Spring的声明试事务
    spring-AOP-添加日志
    弹窗插件
    工厂设计模式
    smartUpload组件批量下载
    简单的C++委托 —— 用模板类实现类成员函数的回调
    偷Microsoft师学MFC艺:且看C++如何支持反射
    C++中回调(CallBack)的使用方法
    epoll 使用实例
    C++成员函数指针的应用
  • 原文地址:https://www.cnblogs.com/haoqirui/p/10296765.html
Copyright © 2011-2022 走看看