一、反射是什么?反射的主要应用场景
1.Golang提供了一种机制,在编译时 不知道类型的情况下 ,可 更新变量 、运行时 查看值 、 调用方法 以及直接对他们的 布局进行操作 的机制,称为反射
2.反射应用场景
a)有时你需要编写一个函数,但是并不知道传给你的参数类型是什么,可能是没约定好;也可能是传入的类型很多,这些类型并不能统一表示。这时反射就会用的上了。
b)有时候需要根据某些条件决定调用哪个函数,比如根据用户的输入来决定。这时就需要对函数和函数的参数进行反射,在运行期间动态地执行函数。
3.反射主要与Golang的 Int erface类型相关,只有interface类型才有反射一说
二、反射reflect包主要方法
1.reflect. Type 和reflect.Value
reflect提供了两种类型来进行访问接口变量的内容:
1)reflect.ValueOf()获取输入参数接口中的数据的值,如果为空则返回 0
2)reflect.TypeOf()动态获取输入参数接口中的值的类型,如果为空则返回 nil
3)reflect.Type和reflect.Value的关系
在go语言中,每个值都包含两个内容:类型和实际的值。从类型角度来看,reflect.Value是一个关于<类型, 实际的值>的二元组,而reflect.Type是值的类型,二者是包含关系。从方法角度来看,reflect.TypeOf 和 (reflect.ValueOf(x)).Type都可以返回reflect.Type;(reflect.ValueOf(x)). Float 可以返回实际的值(类似的方法还包括(reflect.ValueOf(x)).Int、(reflect.ValueOf(x)).Bool等);(reflect.ValueOf(x)).Kind可以返回一个常量定义的类型。
2.reflect.Type和Value的常用方法
1)Type和Value拥有的同名方法
2)Type中独有的方法
3)Value中独有的方法
三、反射示例
1.通过反射修改内容
package main
import (
“reflect”
“fmt”
)
type Language struct {
Name string
}
func main() {
s := &Language{Name: “go”}
v := reflect.ValueOf(s)
// 修改值必须是指针类型
if v.Kind() != reflect.Ptr {
fmt.Println(“not pointer type”)
return
}
// 获取指针所指向的元素
v = v.Elem()
// 获取目标key的Value的封装
name := v.FieldByName(“Name”)
if name.Kind() == reflect.String {
name.SetString(“ python ”)
}
fmt.Printf(“%#v \n”, *s)
}
2.通过反射调用方法
package main
import (
“fmt”
“reflect”
)
type Language struct {
Name string
}
func (s Language) Print(name string){
fmt.Println(“my name is :”, name)
}
func main() {
s := Language{Name: “go”}
v := reflect.ValueOf(s)
m := v.MethodByName(“Print”)
// set parameter
args := []reflect.Value{reflect.ValueOf(“python”)}
// 调用函数
m.Call(args)
}