package main import ( "fmt" "reflect" ) // Human 定义一个名为Human的结构体 type Human struct { Name string // 姓名 Age int // 年龄 Gender string // 性别 } // GetName Human结构体的GetName()方法 func (hum Human) GetName() string { return hum.Name } // GetAge Human结构体的GetAge()方法 func (hum Human) GetAge() int { return hum.Age } // GetGender Human结构体的GetGender()方法 func (hum Human) GetGender() string { return hum.Gender } func reflectTest(v interface{}) { reflectType := reflect.TypeOf(v) reflectTypeKind := reflectType.Kind() reflectTypeKindString := reflectTypeKind.String() fmt.Printf("reflectType = %+v \n", reflectType) // reflectType = *main.Human fmt.Printf("reflectTypeKind = %+v \n", reflectTypeKind) // reflectTypeKind = ptr fmt.Printf("reflectTypeKindString = %+v \n", reflectTypeKindString) // reflectTypeKindString = ptr reflectValue := reflect.ValueOf(v) reflectValueKind := reflectValue.Kind() reflectValueKindString := reflectValueKind.String() fmt.Printf("reflectValue = %+v \n", reflectValue) // reflectValue = &{Name:张三 Age:18 Gender:男} fmt.Printf("reflectValueKind = %+v \n", reflectValueKind) // reflectValueKind = ptr fmt.Printf("reflectValueKindString = %+v \n", reflectValueKindString) // reflectValueKindString = ptr reflectValueElem := reflectValue.Elem() fmt.Printf("reflectValueElem = %+v \n", reflectValueElem) // reflectValueElem = {Name:张三 Age:18 Gender:男} reflectValueElemKind := reflectValueElem.Kind() fmt.Printf("reflectValueElemKind = %+v \n", reflectValueElemKind) // reflectValueElemKind = struct if reflectValueElemKind == reflect.Struct { fmt.Println("形参v是结构体") // 形参v是结构体 // 获取结构体有几个字段,并遍历这些字段 numField := reflectValueElem.NumField() for i := 0; i < numField; i++ { fmt.Printf("第%+v个字段的值为:%+v \n", i, reflectValueElem.Field(i)) } // 第0个字段的值为:张三 // 第1个字段的值为:18 // 第2个字段的值为:男 // 获取结构体有几个方法,并调用一遍这些方法(重要提醒:方法是按ASCII码升序的,不是按定义的先后顺序) numMethod := reflectValueElem.NumMethod() for i := 0; i < numMethod; i++ { ret := reflectValueElem.Method(i).Call(nil) // Call()方法的参数即为结构体方法的参数 fmt.Printf("第%+v个方法的返回值为:%+v \n", i, ret[0]) } // 第0个方法的返回值为:18 // 第1个方法的返回值为:男 // 第2个方法的返回值为:张三 // 检查指定方法是否定义 methodName := "GetWeight" // 未定义的方法名 isValid := reflectValueElem.MethodByName(methodName).IsValid() if isValid { fmt.Printf("%+v()方法存在 \n", methodName) } else { fmt.Printf("%+v()方法不存在 \n", methodName) // GetWeight()方法不存在 } // 检查指定方法是否定义 methodName = "GetName" // 已定义的方法名 isValid = reflectValueElem.MethodByName(methodName).IsValid() if isValid { fmt.Printf("%+v()方法存在 \n", methodName) // GetName()方法存在 ret := reflectValueElem.MethodByName(methodName).Call(nil) fmt.Printf("利用反射调用%+v()方法,返回值为:%+v \n", methodName, ret[0]) // 利用反射调用GetName()方法,返回值为:张三 } else { fmt.Printf("%+v()方法不存在 \n", methodName) } // 检查指定字段是否存在 fieldByName := "Weight" // 不存在的字段 fieldIsValid := reflectValueElem.FieldByName(fieldByName).IsValid() if fieldIsValid { fmt.Printf("%+v字段存在 \n", fieldByName) } else { fmt.Printf("%+v字段不存在 \n", fieldByName) // Weight字段不存在 } // 检查指定字段是否存在 fieldByName = "Age" // 存在的字段名 fieldIsValid = reflectValueElem.FieldByName(fieldByName).IsValid() if fieldIsValid { fmt.Printf("%+v字段存在 \n", fieldByName) // Age字段存在 // 利用反射修改结构体字段的值(重要提醒:字段名首字母需大写才能利用反射修改其值) field := reflectValueElem.FieldByName(fieldByName) fieldKindString := field.Kind().String() if fieldKindString == "int64" || fieldKindString == "int" { field.SetInt(17) } } else { fmt.Printf("%+v字段不存在 \n", fieldByName) } } else { fmt.Println("形参v不是结构体") } } func main() { hum := Human{ Name: "张三", Age: 18, Gender: "男", } reflectTest(&hum) fmt.Printf("hum = %+v \n", hum) // hum = {Name:张三 Age:17 Gender:男} // 由于利用反射修改了Age字段的值,故其值不是18,而是17 } //========== 总结 ==========// // 1、反射属于高级应用,一般开发用不上,通常只有开发框架才会使用反射(在其它语言里也一样,反射多用于开发框架)。
Copyright © 2024 码农人生. All Rights Reserved