变量与反射
1.变量的内在机制
A.类型信息,这部分是元信息,是预先定义好的,比如
1: var arr [10]int2: arr[0] = 103: arr[1] = 204: arr[2] = 305: arr[3] = 406: arr[4] = 50
B.值类型,这部分是程序运行过程中,动态改变的.
1: type Animal struct {2: Name string3: age int4: }5:6: var a Animal
2.反射与空接口
A. 空接口可以存储任何类型的变量
B.那么给你一个空接口,怎么知道里面存储的是什么东西
c.在运行时动态的获取一个变量的类型信息和值类型,就叫反射
3.怎么分析
A.内置包 reflect
B.获取类型信息:reflect.TypeOf
C:获取值信息 reflect.ValueOf
基本数据类型分析(a是一个空接口变量)
打印1: package main2: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.415: reflect_example(x)16: var y float32 = 3.217: reflect_example(y)18: }
1: type of a: float642: type of a: float32
t.Kind()直接获取类型,结果为reflect.Int64,reflect.String等…可以用swtich来判断
reflect.ValueOf获取变量的值相关信息:
1: var x float64 = 3.42: 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()等同于*t13: t.Elem().SetFloat(6.6)14: }15: }16: func main() {17: var x float64 = 9.918: // 注意这里传入的是x的指针19: reflect_set_value(&x)20: fmt.Println("x value:",x)21: }
结构体反射
获取结构体类型相关信息
1: type student struct {2: Name string3: Sex int4: Age int5: }6: func main() {7: var a student8: 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 student3: 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 string3: Sex int4: Age int5: }6: func (s *Student) SetName(name string) {7: s.Name = name8: }9: func (s *Student) Print() {10: fmt.Println(s.Name)11: }12: func main() {13: var a Student14: 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.Value26: 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.Value35: m1.Call(arg2)
结果
1: method numbers 22: 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 Student7: v := reflect.ValueOf(&a)8: t := v.Type()9: field0 := t.Elem().Field(0)10: fmt.Println("tag json =",field0.Tag.Get("json"))11: }
总结
反射就是在运行程序中可以动态地获取一个变量的类型信息和值信息