外贸网站推广有用吗,在浴室里做的网站,石家庄工程职业学院,网站热力图工具本节也是GO核心部分#xff0c;很重要。包括基本类型的反射#xff0c;结构体类型的反射#xff0c;类别方法Kind()#xff0c;修改变量的值。 目录 一、概念#xff0c;基本类型的反射二、结构体类型的反射三、类别方法Kind()四、修改变量的值 一、概念#xff0c;基本…本节也是GO核心部分很重要。包括基本类型的反射结构体类型的反射类别方法Kind()修改变量的值。 目录 一、概念基本类型的反射二、结构体类型的反射三、类别方法Kind()四、修改变量的值 一、概念基本类型的反射
【1】反射可以做什么? 1)反射可以在运行时动态获取变量的各种信息比如变量的类型类别等信息 2)如果是结构体变量还可以获取到结构体本身的信息(包括结构体的字段、方法) 3)通过反射可以修改变量的值可以调用关联的方法。 4)使用反射需要import reflect 【2】反射相关的函数 1)reflect.TypeOf(变量名),获取变量的类型返回reflect.Type类型 2)reflect.ValueOf(变量名),获取变量的值返回reflect.Value类型 反射不仅可以获取变量名和变量类型reflect.Type也可以通过空接口转回原类型
package mainimport (fmtreflect
)func main() {// 定义一个变量var x int 42// 获取变量的类型t : reflect.TypeOf(x)fmt.Println(Type:, t) // 输出: Type: int// 获取变量的值v : reflect.ValueOf(x)fmt.Println(Value:, v) // 输出: Value: 42// 将 reflect.Value 转换回原始类型// Step 1: 将 reflect.Value 转换为 empty interface (interface{})emptyInterface : v.Interface() // 这里使用空接口可以接受任何类型的值// Step 2: 使用类型断言将 empty interface 转换回原始类型 intoriginalValue : emptyInterface.(int) // 将空接口断言为 int 类型fmt.Println(Original value:, originalValue) // 输出: Original value: 42
}
反射和数据类型互转的流程图如下
二、结构体类型的反射
和基本类型的情况差不多但要注意因为实现接口的结构体可能有多个接口转结构体要判断是否转成功
package mainimport (fmtreflect
)// 定义 student 结构体
type student struct {Name stringAge int
}func main() {// 创建一个 student 实例s : student{Name: Alice, Age: 20}// 获取变量的类型t : reflect.TypeOf(s)fmt.Println(类型:, t) // 输出: 类型: main.student// 获取变量的值v : reflect.ValueOf(s)fmt.Println(值:, v) // 输出: 值: {Alice 20}// 将 reflect.Value 转换回原始类型// Step 1: 将 reflect.Value 转换为 empty interface (interface{})emptyInterface : v.Interface() // 这里使用空接口可以接受任何类型的值// Step 2: 使用类型断言将 empty interface 转换回原始类型 studentoriginalStudent, ok : emptyInterface.(student) // 将空接口断言为 student 类型if ok {// 如果转换成功输出姓名和年龄fmt.Printf(原始学生 - 姓名: %s, 年龄: %d\n, originalStudent.Name, originalStudent.Age) // 输出: 原始学生 - 姓名: Alice, 年龄: 20} else {fmt.Println(类型断言为 student 失败。)}
}
三、类别方法Kind()
Kind()是reflect.Type的一个方法用于获取类型的基本种类kind。它返回一个reflect.Kind类型的值用于描述基本数据类型的特性如int、string、struct等。 Kind()和TypeOf()的区别如下表所示
特性reflect.TypeOf()reflect.Kind()返回值返回 reflect.Type 类型的对象返回 reflect.Kind 类型的枚举值作用获取变量的完整类型信息获取变量的基本种类如 int、string、struct适用场景当需要获取类型的详细信息时当只需要判断数据类型的基本特性时
语法TypeOf(s).Kind()或ValueOf(s).Kind()这两个操作都返回变量s的基本类型。
四、修改变量的值
如果用反射修改x的类型需要先获取reflect.Value类型然后用对应x类型的方法比如SetInt()如果x是int*则需要先用Elem()再用SetInt()
package mainimport (fmtreflect
)func main() {var x int 42p : x // 创建指向 x 的指针// 获取指针的 reflect.Valuev : reflect.ValueOf(p)// 使用 Elem() 获取指针指向的值elem : v.Elem()// 修改指针指向的值elem.SetInt(100)// 输出修改后的值fmt.Println(修改后的值:, x) // 输出: 修改后的值: 100
}
如果x是结构体要用Field()获取字段Method()获取方法用reflect.Value切片调用有参方法用nil调用无参方法
package mainimport (fmtreflect
)// 定义 student 结构体
type student struct {Name stringAge int
}// 为 student 结构体定义一个方法
func (s *student) SetAge(age int) {s.Age age
}// 为 student 结构体定义另一个方法
func (s *student) GetInfo() string {return fmt.Sprintf(姓名: %s, 年龄: %d, s.Name, s.Age)
}func main() {// 创建一个 student 实例s : student{Name: Alice, Age: 20}// 获取结构体的类型使用指针获取stuType : reflect.TypeOf(s)// 获取字段数量numFields : stuType.Elem().NumField() // 使用 Elem() 获取底层类型fmt.Printf(字段数量: %d\n, numFields)// 遍历字段for i : 0; i numFields; i {field : stuType.Elem().Field(i) // 使用 Elem() 获取底层类型的字段fmt.Printf(字段名: %s, 字段类型: %s\n, field.Name, field.Type)}// 获取方法数量numMethods : stuType.NumMethod() // 获取方法数量fmt.Printf(方法数量: %d\n, numMethods)// 遍历方法for i : 0; i numMethods; i {method : stuType.Method(i)fmt.Printf(方法名: %s\n, method.Name)}// 使用反射修改 Name 字段的值stuValue : reflect.ValueOf(s) // 获取结构体的反射值使用指针可以修改值nameField : stuValue.Elem().Field(0) // 获取第一个字段的反射值// 确保字段可设置if nameField.CanSet() {nameField.SetString(Bob) // 修改 Name 字段的值为 Bob}// 调用 SetAge 方法将年龄设置为 30setAgeMethod : stuValue.MethodByName(SetAge)args : []reflect.Value{reflect.ValueOf(30)} // 创建包含参数的切片setAgeMethod.Call(args) // 调用 SetAge 方法传入参数// 调用 GetInfo 方法getInfoMethod : stuValue.MethodByName(GetInfo)info : getInfoMethod.Call(nil) // 调用方法传递空参数// 输出信息fmt.Println(info[0]) // 输出: 姓名: Bob, 年龄: 30
}
关键代码解释 1.info : getInfoMethod.Call(nil) infoMethod是通过反射获取到的一个方法的反射值。在这个例子中它指向student结构体的Info方法。Call是reflect.Value类型的方法用于调用一个方法。它接受一个参数参数是一个reflect.Value切片表示要传递给被调用方法的参数。在这里我们传递了nil表示Info方法不需要任何参数。在这个例子中GetInfo方法返回一个字符串因此info将是一个包含一个reflect.Value的切片表示学生信息字符串。 2. args : []reflect.Value{reflect.ValueOf(30)} 这一行创建了一个reflect.Value切片命名为args它将用于调用SetAge方法。reflect.ValueOf(30)用于将整数30转换为reflect.Value类型。[]reflect.Value{}表示创建一个reflect.Value类型的切片作为SetAge方法的参数。