二. 反射
反射是Go语言获取程序运行时类型信息的方式,可以利用这些信息进行一些更加灵活的操作.
Go语言标准库的reflect包中提供李Typeof()和Valueof()函数.
Typeof ( ):获取被反射对象的类型信息;
Valueof ( ):获取被反射对象的值信息.
可以使用这两个函数从接口interface{ }对象中获取实际目标对象的类型和值信息.
1.go语言对基本的数据类型进行反射操作
import (
"fmt"
"reflect"
)
func main() {
var pi float64 = 3.14
t := reflect.TypeOf(pi)
v := reflect.ValueOf(pi)
fmt.Println("---",t,v)
fmt.Println("Type:",t.Kind())
fmt.Println("Value:", v.Float())
}
运行结果:
--- float64 3.14
Type: float64
Value: 3.14
2.go语言对结构体进行反射操作
package main
import (
"fmt"
"reflect"
)
func main() {
stu := Monitor{Student{10001,"liming",false,90.5},"班长"}
t := reflect.TypeOf(stu) //获取反射对象的类型信息 : 此处t 为 main.Monitor
v := reflect.ValueOf(stu)//获取反射对象的值信息 : 此处v 为 {{10001 liming false 90.5} 班长}
fmt.Println("---t.NumField()---:", t.NumField()) //获取反射对象main.Monitor的长度信息 : 此处结构体Monitor为2
fmt.Println("--t--:",t)
fmt.Println("--v--:",v)
/*
说明:
反射会将匿名字段当作一个独立字段处理,如果要获取嵌入字段的Type和Value信息,必须使用buoying路径来完成.
通过Value类型的FieldByIndex()方法获取嵌入字段的所以路径,FieldByIndex()原型定义:
func (v value) FieldByIndex( index []int) value
FieldByIndex()执行成功会返回嵌入字段的索引路径,如果对一个非struct类型执行FieldByIndex()方法会产生panic错误事件.
*/
for i := 0; i < t.NumField(); i++ {
fmt.Println("--t.Field(i)--",i,t.Field(i))
if t.Field(i).Anonymous { //Anonymous判断每个字段是否为匿名字段
fmt.Println("--v.Field(i)--",v.Field(i))
for j := 0; j < v.Field(i).NumField();j++{
fmt.Println("Embedded fields:",v.FieldByIndex([]int{i,j}).Interface())//FieldByIndex([]int{i,j})索引访问每个嵌入式字段的值
}
}else{
fmt.Println("Embedded fields:",v.Field(i).Interface())
}
}
}
type Student struct {
Id int
Name string
Sex bool
Grade float32
}
type Monitor struct {
Student //Student为Monitor的匿名字段
As string
}
运行结果:
---t.NumField()---: 2
--t--: main.Monitor
--v--: {{10001 liming false 90.5} 班长}
--t.Field(i)-- 0 {Student main.Student 0 [0] true}
--v.Field(i)-- {10001 liming false 90.5}
Embedded fields: 10001
Embedded fields: liming
Embedded fields: false
Embedded fields: 90.5
--t.Field(i)-- 1 {As string 32 [1] false}
Embedded fields: 班长
详细函数说明见go的reflect机制和reflect包: https://studygolang.com/articles/1256