Go - 反射
反射的概念
-
正常情况下,代码写完,通过编译器编译成机器代码后,运行的过程就已经确定了,就像你已经编好了剧本,一旦你把剧本交到台上,演员就会按照剧本来表演,此时你再也无法干剧情的发展。
-
对应于反射,我们大部分使用正射场景。在正射场景中,一个结构体的创建和结构体内的具体字段名称,都是确定的,一旦编译了以后就无法更改。但是在反射中,可以动态的创建结构体和在结构体中增添字段。
-
在 go 语言中,反射核心使用只有两个方法
- oType := reflect.TypeOf(object)
- oValue := reflect.ValueOf(object)
-
反射作用,获取对象信息,获取对象属性值,调用对象的方法。
go语言调用的简单实例
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
}
func (p Person) SayHellow() {
fmt.Println("hellow")
}
func main() {
p := Person{
Name: "张三",
Age: 18,
}
typeAPI(p)
valueAPI(p)
}
func typeAPI(obj interface{}) {
OType := reflect.TypeOf(obj)
oKind := OType.Kind()
fmt.Println("oType", OType)
fmt.Println("oKind", oKind)
fmt.Println("oTypeName", OType.Name())
//获取属性和方法的个数
fmt.Println("属性的个数", OType.NumField())
fmt.Println("方法的个数", OType.NumMethod())
//遍历所有的属性
for i := 0; i < OType.NumField(); i++ {
structField := OType.Field(i)
fmt.Println("第", i, "个属性的名称和内容", structField.Name, structField.Type)
}
//遍历所有的方法
for i := 0; i < OType.NumMethod(); i++ {
method := OType.Method(i)
fmt.Println("第", i, "方法的属性和名称", method.Type, method.Name)
}
}
func valueAPI(obj interface{}) {
oValue := reflect.ValueOf(obj)
fmt.Println("ovalue", oValue)
fmt.Println("kind原始数据", oValue.Kind())
// 查看 p 的所有的属性值
for i := 0; i < oValue.NumField(); i++ {
fmt.Println("第", i, "个属性的属性值", oValue.Field(i).Interface()) //打印属性的正射形式
}
}
go语言反射的功能
在拿到一个结构体时,即不知道对方是啥,也不知道对象有什么方法,当时我依旧可以操作你,这就是反射的强大之处。
参考文献
https://www.bilibili.com/video/BV1Z4411J7sZ?p=3&share_source=copy_web