go语言反射
时间:2022-07-24
本文章向大家介绍go语言反射,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
反射的特点
- 反射功能具有强大的功能
- 反射是用程序检查其所拥有的结构,尤其是类型的一种能力
- 是元编程的一种形式
- 我们可以在【运行时】通过反射来分析一个结构体
- 检查其类型和变量(类型和取值)和方法
- 动态的修改变量和调用方法
- 这对于没有源代码的包尤其有用
- 这是一个强大的工具,除非真的有必要,否则应当避免使用或者小心使用
反射API
TypeOf
oType := reflect.TypeOf(obj)
t.Name()
kind := oType.Kind()
kind:struct 系统类型的枚举
type: 具体的类
t.NumField()
t.NumMethod()
structField := oType.Field(i)
structField.Name
structField.Type
method := oType.Method(i)
methodType := methodType
argNum := method.Type.NumIn() 参数个数
artType := method.Type.In(0) 第1个参数类型
t.FieldByIndex([]int{0, 1})
找出第0个父结构体中的第1个属性
ValueOf
oValue := reflect.ValueOf(obj) field := oValue.Field(i) -> fieldValue :=value.Field(i).Interface{}(获取第i个属性的值的“正射”形式)
fieldValue := value.FieldByIndex([]int{0, 0}).Interface() 找出第0个父结构体中的第0个属性值
oPtrValue.Elem() 获取地址value中的值value
oPtrValue.Elem().CanSet() 检查当前地址value内的值是否可以改变(可改变条件:可寻址+不来字非导出字段)
oPtrValue.Elem().SetInt(999)
value.SetString("jack")
nameValue := value.FieldByName("Name")
isVaild := value.IsVaild() nil(0值)非法 非常罕见
kind := value.Kind()和type.Kind()一样
mathod := oValue.Method(i) 通过方法的值可以调取方法
methodValue.Call([]reflect.Value{val1,val2})
代码实例(简单类型的反射操作)
package main
import (
"fmt"
"reflect"
)
//简单类型的反射
func reflectTest01(b interface{}) {
//通过反射来获取传入变量的 type,kind。值
//1.先获取到reflect.Type
rType := reflect.TypeOf(b)
fmt.Println("rType = ", rType)
//2.获取到reflect.Value
rVal := reflect.ValueOf(b)
n2 := 2 + rVal.Int()
fmt.Println("n2 = ", n2)
fmt.Printf("rVal = %v, rVal type=%Tn", rVal, rVal)
//下面我们将rVal转换成interface
iv := rVal.Interface()
//将interface通过断言转换成需要的类型
num2 := iv.(int)
fmt.Println("num2 = ", num2)
}
//复杂类型的反射
func reflectTest02(b interface{}) {
//通过反射获取到传入变量的type kind值
rType := reflect.TypeOf(b)
fmt.Println("rType =", rType)
//获取到reflectValue
rVal := reflect.ValueOf(b)
//获取变量对应的kind
typeKind := rType.Kind()
valKind := rVal.Kind()
fmt.Printf("typeKind = %v, valKind = %vn", typeKind, valKind)
//将rVal转换为interface{}
iv := rVal.Interface()
fmt.Printf("iv = %v is type =%Tn", iv, iv)
//把interface{}通过断言转换成需要的类型
stu, ok := iv.(Student)
if ok {
fmt.Println("stu.Name = ", stu.Name)
}
}
func changeValue(b interface{}) {
rVal := reflect.ValueOf(b)
fmt.Printf("rVal kind =%vn", rVal.Kind())
rVal.Elem().SetInt(1)
}
type Student struct {
Name string
Age int
}
func main() {
var b int = 10
reflectTest01(b)
fmt.Println("-------------")
stu := Student{
Name: "tom",
Age: 12,
}
reflectTest02(stu)
fmt.Println("-------------")
var c int = 100
changeValue(&c)
fmt.Println(c)
}
反射操作相关代码(结构体)
package main
import (
"fmt"
"reflect"
)
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Score float32
Sex string
}
func (s Monster) Print() {
fmt.Println("-----start-------")
fmt.Println(s)
fmt.Println("-----end-------")
}
func (s Monster) GetSum(n1, n2 int) int {
return n1 + n2
}
func (s Monster) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
}
func TestStruct(a interface{}) {
rType := reflect.TypeOf(a)
rVal := reflect.ValueOf(a)
kd := rVal.Kind()
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
num := rVal.NumField()
fmt.Println("struct fields:", num)
//变量结构体的所有字段
for i := 0; i < num; i++ {
fmt.Printf("field %d:值为:%vn", i, rVal.Field(i))
tagVal := rType.Field(i).Tag.Get("json")
if tagVal != "" {
fmt.Printf("field %d: tag为=%vn", i, tagVal)
}
}
//结构体的方法操作
numOfMethod := rVal.NumMethod()
fmt.Printf("struct has %d methodsn", numOfMethod)
//var params []reflect.Value
rVal.Method(1).Call(nil)
//调用结构体的第1个方法Method(0)
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := rVal.Method(0).Call(params)
fmt.Println("res = ", res[0].Int())
//反射修改字段
}
func main() {
var a Monster = Monster{
Name: "tom",
Age: 100,
Score: 30.1,
Sex: "男",
}
TestStruct(a)
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【redis入门】Centos下安装redis
- LeetCode精选好题(五)
- 【leetcode两题选手】MySQL类题目(一)
- 【LeetCode每日一题】(8.11)被围绕的区域
- 二叉树的前中后序遍历(迭代法)(带动画)
- 【LeetCode两题选手】算法类题目(8.8)
- 【LeetCode每日一题】(8.9)复原IP地址(回溯)
- 【回溯算法】N叉树相关技巧
- 【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练
- 数据结构练手小项目(AVL树、哈希表、循环链表、MySQL数据库)
- 【LeetCode】每日一题(8.2)二叉树展开为链表
- 【小技巧】argc和argv的用法
- 全面分析redis持久化机制
- 【奇技淫巧】-- 接雨水
- 【奇技淫巧】-- 最长连续序列