import("fmt""reflect""testing")funcTestTypeAndValue(t *testing.T){var f int64=10
t.Log(reflect.TypeOf(f),reflect.ValueOf(f))
t.Log(reflect.ValueOf(f).Type())}funcCheckType(v interface{}){//空接口可以接受所有类型
t := reflect.TypeOf(v)switch t.Kind(){case reflect.Float32,reflect.Float64:
fmt.Println("Float")case reflect.Int,reflect.Int32,reflect.Int64:
fmt.Println("Interger")default:
fmt.Println("Unknow",t)}}funcTestBasicType(t * testing.T){var f float64=12CheckType(f)}funcTestDeepEqual(t *testing.T){}type Employee struct{
EmployeeID string
Name string"format:'normal'"//struct Tag
Age int}func(e *Employee)UpdateAge(newVal int){
e.Age = newVal
}type Customer struct{
CookieID string
Name string
Age int}funcTestInvokeByName(t *testing.T){
e :=&Employee{"1","Mike",30}//按照名字获取成员 通过反射的方式 直接返回了名字的值
t.Logf("Name value(%[1]v),Type(%[1]T)",reflect.ValueOf(*e).FieldByName("Name"))if nameField,ok := reflect.TypeOf(*e).FieldByName("Name");!ok{//返回两个值 ok代表 有没有这个值
t.Error("Failed to get 'Name' field")}else{
t.Log("Tag:format",nameField.Tag.Get("format"))}
reflect.ValueOf(e).MethodByName("UpdateAge").Call([]reflect.Value{reflect.ValueOf(1)})
t.Log("Update Age:",e)}//名字和结构体的对应 都是通过 structTag
反射的万能编程
package ch38
import("errors""reflect""testing")type Employee struct{
Employee string
Name string
Age int}type Customer struct{
CookieID string
Name string
Age int}func(e *Employee)UpdateAge(newVal int){
e.Age = newVal
}// 切片和map只能和空集进行比较funcTestDeepEqual(t *testing.T){
a :=map[int]string{1:"one",2:"two",3:"three"}
b :=map[int]string{1:"one",2:"two",3:"three"}//t.Log(a == b)
t.Log(reflect.DeepEqual(a,b))
s1 :=[]int{1,2,3}
s2 :=[]int{2,4,6}
s3 :=[]int{1,4,6}//t.Log(s1 == s2)
t.Log(reflect.DeepEqual(s1,s2))
t.Log(reflect.DeepEqual(s2,s3))}//关于反射的要求//提高了程序的灵活性 降低了程序的可读性 降低了程序的性能//构建一个 通用的填充方法//公共方法解决不同结构体的填充funcfillBySettings(st interface{},settings map[string]interface{})error{//func (v value) Elem() Value//Elem returns the value that the interface{} v contains or that the pointer//It panics if v's Kind is notif reflect.TypeOf(st).Kind()!= reflect.Ptr{//elem()获取指针指向的值if reflect.TypeOf(st).Elem().Kind()!= reflect.Struct{//判断是不是结构//如果不满足以上条件 不是指针也不是结构 就会返回return errors.New("the first param should be a pointer to the struct type")}}if settings ==nil{return errors.New("settings is nil")}var(
field reflect.StructField
ok bool)//传入的是一个指针类型 FieldByName只能从结构类型上去获得//从指针类型到指针类型指向的结构,需要使用一个Elem()这样的方法处理 获得了指针指向的结构//便利存入的Map k代表类型名字 观测本程序当中是否是Field的名字for k,v :=range settings{if field,ok =(reflect.ValueOf(st)).Elem().Type().FieldByName(k);!ok{continue}//Map和field的类型一致if field.Type == reflect.TypeOf(v){
vstr := reflect.ValueOf(st)
vstr = vstr.Elem()//满足条件后 就设置 Value部 分
vstr.FieldByName(k).Set(reflect.ValueOf(v))}}returnnil}funcTestFillNameAndAge(t *testing.T){
settings :=map[string]interface{}{"Name":"Mike","Age":40}
e := Employee{}if err :=fillBySettings(&e,settings);err !=nil{
t.Fatal(err)}
t.Log(e)
c:=new(Customer)if err :=fillBySettings(c,settings);err !=nil{
t.Fatal(err)}
t.Log(*c)}//和配置有关的程序 需要灵活性的程序 我们都可以使用反射完成//在性能特别高的情况下 我们要注意 可读性疯狂下降