typeUser := reflect.TypeOf(common.User{}) //需要用struct的Type,不能用指针的Type fieldNum := typeUser.NumField() //成员变量的个数 for i := 0; i < fieldNum; i++ { field := typeUser.Field(i) fmt.Printf("%d %s offset %d anonymous %t type %s exported %t json tag %s\n", i, field.Name, //变量名称 field.Offset, //相对于结构体首地址的内存偏移量,string类型会占据16个字节 field.Anonymous, //是否为匿名成员 field.Type, //数据类型,reflect.Type类型 field.IsExported(), //包外是否可见(即是否以大写字母开头) field.Tag.Get("json")) //获取成员变量后面``里面定义的tag } fmt.Println()
//可以通过FieldByName获取Field if nameField, ok := typeUser.FieldByName("Name"); ok { fmt.Printf("Name is exported %t\n", nameField.IsExported()) } //也可以根据FieldByIndex获取Field thirdField := typeUser.FieldByIndex([]int{2}) //参数是个slice,因为有struct嵌套的情况 fmt.Printf("third field name %s\n", thirdField.Name)
2.4 获取struct成员方法的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14
typeUser := reflect.TypeOf(common.User{}) methodNum := typeUser.NumMethod() //成员方法的个数。接收者为指针的方法【不】包含在内 for i := 0; i < methodNum; i++ { method := typeUser.Method(i) fmt.Printf("method name:%s ,type:%s, exported:%t\n", method.Name, method.Type, method.IsExported()) } fmt.Println()
typeUser2 := reflect.TypeOf(&common.User{}) methodNum = typeUser2.NumMethod() //成员方法的个数。接收者为指针或值的方法【都】包含在内,也就是说值实现的方法指针也实现了(反之不成立) for i := 0; i < methodNum; i++ { method := typeUser2.Method(i) fmt.Printf("method name:%s ,type:%s, exported:%t\n", method.Name, method.Type, method.IsExported()) }
2.5 获取函数的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
func Add(a, b int) int { return a + b }
typeFunc := reflect.TypeOf(Add) //获取函数类型 fmt.Printf("is function type %t\n", typeFunc.Kind() == reflect.Func) argInNum := typeFunc.NumIn() //输入参数的个数 argOutNum := typeFunc.NumOut() //输出参数的个数 for i := 0; i < argInNum; i++ { argTyp := typeFunc.In(i) fmt.Printf("第%d个输入参数的类型%s\n", i, argTyp) } for i := 0; i < argOutNum; i++ { argTyp := typeFunc.Out(i) fmt.Printf("第%d个输出参数的类型%s\n", i, argTyp) }
fmt.Printf("origin value iValue is %d %d\n", iValue.Interface().(int), iValue.Int()) fmt.Printf("origin value sValue is %s %s\n", sValue.Interface().(string), sValue.String()) user := userValue.Interface().(common.User) fmt.Printf("id=%d name=%s weight=%.2f height=%.2f\n", user.Id, user.Name, user.Weight, user.Height) user2 := userPtrValue.Interface().(*common.User) fmt.Printf("id=%d name=%s weight=%.2f height=%.2f\n", user2.Id, user2.Name, user2.Weight, user2.Height)
3.5 空Value的判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var i interface{} //接口没有指向具体的值 v := reflect.ValueOf(i) fmt.Printf("v持有值 %t, type of v is Invalid %t\n", v.IsValid(), v.Kind() == reflect.Invalid)
var user *common.User = nil v = reflect.ValueOf(user) //Value指向一个nil if v.IsValid() { fmt.Printf("v持有的值是nil %t\n", v.IsNil()) //调用IsNil()前先确保IsValid(),否则会panic }
var u common.User //只声明,里面的值都是0值 v = reflect.ValueOf(u) if v.IsValid() { fmt.Printf("v持有的值是对应类型的0值 %t\n", v.IsZero()) //调用IsZero()前先确保IsValid(),否则会panic }
3.6 通过Value修改原始数据的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var i int = 10 var s string = "hello" user := common.User{ Id: 7, Name: "杰克逊", Weight: 65.5, Height: 1.68, }
sliceValue := reflect.ValueOf(&users) //准备通过Value修改users,所以传users的地址 if sliceValue.Elem().Len() > 0 { //取得slice的长度 sliceValue.Elem().Index(0).Elem().FieldByName("Name").SetString("令狐一刀") fmt.Printf("1st user name change to %s\n", users[0].Name) }
甚至可以修改slice的cap,新的cap必须位于原始的len到cap之间,即只能把cap改小。
sliceValue.Elem().SetCap(3)
通过把len改大,可以实现向slice中追加元素的功能。
1 2 3 4 5 6 7 8 9
sliceValue.Elem().SetLen(2) //调用reflect.Value的Set()函数修改其底层指向的原始数据 sliceValue.Elem().Index(1).Set(reflect.ValueOf(&common.User{ Id: 8, Name: "李达", Weight: 80, Height: 180, })) fmt.Printf("2nd user name %s\n", users[1].Name)
user :=t := reflect.TypeOf(common.User{}) value := reflect.New(t) //根据reflect.Type创建一个对象,得到该对象的指针,再根据指针提到reflect.Value value.Elem().FieldByName("Id").SetInt(10) user := value.Interface().(*common.User) //把反射类型转成go原始数据类型Call([]reflect.Value{})
4.2 创建slice
1 2 3 4 5 6 7 8 9 10 11
var slice []common.User sliceType := reflect.TypeOf(slice) sliceValue := reflect.MakeSlice(sliceType, 1, 3) sliceValue.Index(0).Set(reflect.ValueOf(common.User{ Id: 8, Name: "李达", Weight: 80, Height: 180, })) users := sliceValue.Interface().([]common.User) fmt.Printf("1st user name %s\n", users[0].Name)