9.1 Go 反射
反射:可以在运行时,动态获取变量的信息
,比如变量的类型,类别
1.对于结构体变量,还可以获取到结构体的字段,方法
2.实现这个功能的是 reflect包
reflect.TypeOf(),获取变量的类型,返回reflect.Type类型 reflect.ValueOf(),获取变量的值,返回reflect.Value类型 reflect.Value.Kind(),获取变量的类别,返回一个常量 reflect.Value.Interface(),转换成interface{}类型
使用反射场景,json序列化
package main import ( "encoding/json" "fmt" ) type Student struct { Name string `json:"学生名"` Age int `json:"学生年纪"` Class string `json:"班级"` } func main() { stu := Student{ "尼古拉斯赵四", 18, "舞王班", } data, err := json.Marshal(stu) if err != nil { fmt.Println("序列化出错", err) } fmt.Println("json序列化结果:", string(data)) }
反射获取基本类型
package main import ( "fmt" "reflect" ) func main() { var num int64 = 12345 fmt.Println("num类型", reflect.TypeOf(num)) //获取变量的值 resNum := reflect.ValueOf(num) fmt.Printf("类型:%T 值:%v\n", resNum, resNum) fmt.Printf("resNum值:%v\n", resNum) fmt.Printf("resNum类型:%v\n", resNum.Type()) fmt.Printf("resNum种类:%v\n", resNum.Kind()) fmt.Printf("resNum确认值:%v\n", resNum.Int()) }
反射获取结构体
package main import ( "fmt" "reflect" ) //学生结构体 type Student struct { Name string Age int Score float32 } //函数接收类型是接口,可以接收任何类型 func test(b interface{}) { t := reflect.TypeOf(b) fmt.Println("参数类型:", t) v := reflect.ValueOf(b) fmt.Println("参数值:", v) k := v.Kind() fmt.Println("参数种类:", k) //转化为接口返回 iv := v.Interface() fmt.Printf("类型:%T 值:%v\n", iv, iv) //类型断言,如果这个接口是student类型 stu, ok := iv.(Student) if ok { fmt.Printf("结构体值:%v 类型:%T\n", stu, stu) } } func main() { var a Student = Student{ Name: "周星驰", Age: 18, Score: 99, } //传入结构体 test(a) }
反射elem获取指针指向的变量
package main import ( "fmt" "reflect" ) //fv.Elem()用来获取指针指向的变量 func testInt(b interface{}) { //获取b的类型 val := reflect.ValueOf(b) fmt.Printf("参数b的类型是:%T 值是:%v\n", val, val) fmt.Printf("val.Elem()获取到变量的类型:%T 值:%v\n", val.Elem(), val.Elem()) //修改val的值 val.Elem().SetInt(100) //返回 一个int值类型 c := val.Elem().Int() fmt.Printf("类型:%T 值是:%d\n", c, c) } func main() { var b int = 1 b = 200 testInt(&b) fmt.Println("b的值:", b) }
理解reflect.Value.Elem()
package main import ( "fmt" "reflect" ) func main() { var num int = 100 //返回变量的值,传入地址,那就是内存地址的值 fn := reflect.ValueOf(&num) //修改指针指向的值,也就是修改num的值 fn.Elem().SetInt(222) fmt.Printf("此时num的值:%d\n", num) //以上操作,等同于 var num2 = 111 var b *int = &num2 *b = 333 fmt.Printf("b的类型:%T\n", b) fmt.Println(num2) }