• Go语言~反射


    reflect包

    • type name和type kind
    • ValueOf
    • 通过反射获取值
    • 通过反射设置变量的值
    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func reflectType(x interface{}) {
    	obj := reflect.TypeOf(x)
    	fmt.Println(obj, obj.Name(), obj.Kind())
    	fmt.Printf("obj type of %T\n", obj)
    }
    
    func reflectValue(x interface{}) {
    	v := reflect.ValueOf(x)
    	fmt.Printf("value is a %v, type is a %T\n", v, v)
    	// 如何得到一个传入时候类型的变量
    	k := v.Kind() // 拿到值对应的类型种类
    	switch k {
    	case reflect.Float32:
    		ret := float32(v.Float())
    		fmt.Printf("value is a %v, type is a %T\n", ret, ret)
    	case reflect.Int32:
    		ret := int32(v.Int())
    		fmt.Printf("value is a %v, type is a %T\n", ret, ret)
    	}
    }
    
    func reflectSetValue(x interface{}) {
    	v := reflect.ValueOf(x)
    	// Elem()用来根据指针取对应的值
    	k := v.Elem().Kind()
    	switch k {
    	case reflect.Int32:
    		v.Elem().SetInt(100)
    	case reflect.Float32:
    		v.Elem().SetFloat(5.678)
    	}
    }
    
    type Cat struct{}
    
    type Dog struct{}
    
    func main() {
    	/*
    		var a float32 = 3.1415926
    		reflectType(a)
    
    		var b int8 = 10
    		reflectType(b)
    		// 结构体类型
    		var c Cat
    		reflectType(c)
    
    		var d Dog
    		reflectType(d)
    
    		// slice
    		var e []string
    		reflectType(e)
    
    		var f []int
    		reflectType(f)
    	*/
    
    	// valueOf
    	/*
    		var aa int32 = 100
    		reflectValue(aa)
    
    		var bb float32 = 3.1415926
    		reflectValue(bb)
    	*/
    
    	// setValue
    	var cc int32 = 10
    	reflectSetValue(&cc)
    	fmt.Println(cc)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    isNil()和isValid()

    package main
    
    // IsNil()常被用于判断指针是否为空;IsValid()常被用于判定返回值是否有效。
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type StructField struct {
    	// Name是字段的名字。PkgPath是非导出字段的包路径,对导出字段该字段为""
    	Name      string
    	PkgPath   string
    	Type      reflect.Type
    	Tag       reflect.StructTag
    	Offset    uintptr
    	Index     []int
    	Anonymous bool
    }
    
    func main() {
    	// *int类型空指针
    	var a *int
    	fmt.Println("var a *int IsNil:", reflect.ValueOf(a).IsNil())
    	// nil值
    	fmt.Println("nil IsValid:", reflect.ValueOf(nil).IsValid())
    	// 实例化一个匿名结构体
    	b := struct{}{}
    	// 尝试从结构体中查找"abc"字段
    	fmt.Println("不存在的结构体成员:", reflect.ValueOf(b).FieldByName("abc").IsValid())
    	// 尝试从结构体中查找"abc"方法
    	fmt.Println("不存在的结构体方法:", reflect.ValueOf(b).MethodByName("abc").IsValid())
    	// map
    	c := map[string]int{}
    	// 尝试从map中查找一个不存在的键
    	fmt.Println("map中不存在的键:", reflect.ValueOf(c).MapIndex(reflect.ValueOf("娜扎")).IsValid())
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    结构体反射

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 结构体反射
    
    type student struct {
    	Name  string `json:"name" ini:"s_name"`
    	Score int    `json:"score" ini:"s_score"`
    }
    
    // 给student添加两个方法 Study和Sleep(注意首字母大写)
    func (s student) Study() string {
    	msg := "好好学习,天天向上。"
    	fmt.Println(msg)
    	return msg
    }
    
    func (s student) Sleep() string {
    	msg := "好好睡觉,快快长大。"
    	fmt.Println(msg)
    	return msg
    }
    
    // 根据反射获取结构体中方法的函数
    func printMethod(x interface{}) {
    	t := reflect.TypeOf(x)
    	fmt.Println(t.NumMethod())
    
    	v := reflect.ValueOf(x)
    	// 因为下面需要拿到具体的方法去调用,所以使用的是值信息
    	for i := 0; i < v.NumMethod(); i++ {
    		methodType := v.Method(i).Type()
    		fmt.Printf("method name:%s\n", t.Method(i).Name)
    		fmt.Printf("method:%s\n", methodType)
    		// 通过反射调用方法传递的参数必须是 []reflect.Value 类型
    		var args = []reflect.Value{}
    		v.Method(i).Call(args) // 调用方法
    	}
    	// 通过方法名获取结构体的方法
    	// t.MethodByName("Sleep") // reflect.Method, bool
    	methodObj := v.MethodByName("Sleep") // reflect.Value
    	fmt.Println(methodObj.Type())
    }
    
    func main() {
    	stu1 := student{
    		Name:  "枫林神",
    		Score: 90,
    	}
    
    	/*
    	// 通过反射区获取结构体中的所有字段信息
    	t := reflect.TypeOf(stu1)
    	fmt.Printf("name :%v kind :%v\n", t.Name(), t.Kind())
    	// 遍历结构体变量的所有字段
    	for i := 0; i < t.NumField(); i++ {
    		//根据结构体字段的索引取字段
    		filedobj := t.Field(i)
    		fmt.Printf("name:%v type:%v tag:%v\n", filedobj.Name, filedobj.Type, filedobj.Tag)
    		fmt.Println(filedobj.Tag.Get("json"), filedobj.Tag.Get("ini"))
    	}
    
    	// 根据名字取结构体中的字段
    	filedobj2, ok := t.FieldByName("Score")
    	if ok {
    		fmt.Printf("name:%v type:%v tag:%v\n", filedobj2.Name, filedobj2.Type, filedobj2.Tag)
    	}
    	*/
    	printMethod(stu1)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
  • 相关阅读:
    patch-package给依赖打补丁实例详解
    值得你收藏的Notes应用模板
    最新下载:Paragon NTFS for Mac 15【软件附加安装教程】
    STM32(TIM定时器中断)
    elasticsearch-1.7.1 (es Windows 64) 安装、启动、停止的详细记录
    外键必须是另一个表的主键吗 ?
    基于强化学习的节能路由(Matlab代码实现)
    过午不食有依据吗
    【Linux】常见指令(二)
    惯性导航方法现有成果综述(2022年持续更新)
  • 原文地址:https://blog.csdn.net/chengyinwu/article/details/134278792