Go基础之--反射
反射:可以在运行时动态获取变量的相关信息
反射需要导入reflect
反射中重要函数的演示
反射有几下几个重要的函数: reflect.TypeOf :获取变量的类型,返回reflect.Type类型 reflect.ValueOf:获取变量的值,返回reflect.Value类型 reflect.Value.Kind:获取变量的类别,返回一个常量 reflect.Value.Interface():转换成interface{}类型
通过一个小例子来理解:
package main
import (
"reflect"
"fmt"
)
type Student struct{
Name string
Age int
}
func (s*Student) SetName(name string){
s.Name="coders"
}
func (s*Student)SetAge(age int){
s.Age = 23
}
func getTypeInfo(a interface{}){
// 用于获取一个数据的数据类型
typeInfo := reflect.TypeOf(a)
kind := typeInfo.Kind()
fmt.Println("kind of a :",kind)
num := typeInfo.NumMethod() //获取当前数据有多少个方法
fmt.Println("method num:",num)
method,ok:=typeInfo.MethodByName("SetName") //获取是否有某个方法
if !ok{
fmt.Println("not have method SetName")
}else{
fmt.Println(method)
}
}
func getAllMethod(a interface{}){
// 用于获取变量下的所有方法
typeInfo := reflect.TypeOf(a)
num := typeInfo.NumMethod()
for i:=0;i<num;i++ {
method:= typeInfo.Method(i)
fmt.Println(method)
}
}
func testGetAllMethod() {
var stu Student
getAllMethod(&stu)
}
func testGetTypeInfo(){
var i int
getTypeInfo(i) //获取的结果就是int
var stu Student
getTypeInfo(&stu) //获取的结果就是struct
getAllMethod(&stu)
var s []int
getTypeInfo(s) //获取的结果就是slice
var a [5]int
getTypeInfo(a) //获取的结果就是array
}
func testGetValueInfo(){
var i = 100
valueInfo := reflect.ValueOf(i)
tmp := valueInfo.Interface() //转换成interface类型
val := tmp.(int) //这里我是知道是int所以直接转换了
fmt.Println("val:",val) //这里获取的还是100
fmt.Println("val of valueInfo:",valueInfo.Int()) // 这里打印的也是100
fmt.Println("type:",valueInfo.Type())
fmt.Println("kind:",valueInfo.Kind())
}
func main(){
testGetTypeInfo()
testGetAllMethod()
testGetValueInfo()
}
上面这个例子中演示了reflect.Value.Kind()可以返回int,struct,slice,array,当然这里可以返回的类型还有很多如下: Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Ptr Slice String Struct UnsafePointer
获取变量的值
reflect.ValueOf(x).Float() reflect.ValueOf(x).Int() reflect.ValueOf(x).String() reflect.ValueOf(x).Bool()
这个功能在上面的代码中也有演示
通过反射来改变变量的值
reflect.Value.SetXX相关方法,如: reflect.Value.SetFloat():设置浮点数 reflect.Value.SetInt():设置整数 reflect.Value.SetString():设置字符串
通过下面一个简单的例子来演示:
package main
import (
"reflect"
"fmt"
)
func main() {
var a float64
fmt.Println(a)
fv := reflect.ValueOf(a)
fv.SetFloat(3.14)
fmt.Println(a)
}
上面这段代码会提示如下错误:
这里需要知道的是我们的变量a是一个值类型的变量,我们通过reflect.valueOf传入的时候其实是传入的变量的拷贝,所以我们如果通过SetFloat给变量设置值的时候其实并不会生效,go这里已经替我考虑到了,所以给我们提示了上面这个错误信息,那是不是我们在reflect.Value的传入地址就可以了呢,我把上述代码中更改为:reflect.Value(&a),当我们运行后发现还是报了和上面相同的错误,这是为什么呢?
我们应该还记得如果是一个指针的时候我们赋值的时候是需要在指针的左边写个*符号,但是这是在反射里面我们怎么写星号,所以go在这里提供给我们另外一个方法,当我们通过调用SetFloat的时候用: fv.Elem().SetFloat(3.14)这种方式调用就ok了,完整的正确代码为:
package main
import (
"reflect"
"fmt"
)
func main() {
var a float64
fmt.Println(a)
fv := reflect.ValueOf(&a)
fv.Elem().SetFloat(3.14)
fmt.Println(a)
}
反射操作结构体
reflect.Value.NumField():获取结构体中字段的个数 reflect.Value.Method(n).Call():调用结构体中的方法
package main
import (
"reflect"
"fmt"
)
type Student struct{
Name string
Age int
Sex int
}
func (s *Student) Set(name string,age int,sex int){
s.Name = name
s.Age = age
s.Sex = sex
}
func testStruct() {
var stu *Student = &Student{}
stu.Set("coder",23,1)
valueInfo := reflect.ValueOf(stu)
fieldNum := valueInfo.Elem().NumField()
fmt.Println("filed num:",fieldNum) //这里返回的结果是3
sexValueInfo := valueInfo.Elem().FieldByName("Sex")
fmt.Println("sex=",sexValueInfo.Int())
sexValueInfo.SetInt(0) //这里是更改值
fmt.Println(stu)
setMethod := valueInfo.MethodByName("Set") //获取Set方法
var params []reflect.Value
name := "tom"
age := 18
sex:=2
params = append(params,reflect.ValueOf(name),reflect.ValueOf(age),reflect.ValueOf(sex))
setMethod.Call(params) //调用Set方法
fmt.Println(stu) //将最开始的值已经更改了
}
func main() {
testStruct()
}
- python面向对象
- 字符串hash入门
- R语言数据处理——数据合并与追加
- python爬取链家租房之获取房屋页面的详细信息(房名,地址,房价,面积,url)
- 信用卡“坏账”客户分析(二)
- Mac上提升python运算速度-PyPy初体验
- python处理json数据(复杂的json转化成嵌套字典并处理)
- Pointer-network理论及tensorflow实战
- python3 log文件处理获取某天需要的数据
- 实战深度强化学习DQN-理论和实践
- Python 工匠:编写条件分支代码的技巧
- python3 下 Zabbix监控调用graph.get并且下载监控图
- 用R语言复盘美国总统大选结果~
- 最新Apache Spark平台的NLP库,助你轻松搞定自然语言处理任务
- 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 数组属性和方法
- 前端模块化开发--ES6相关知识
- (一)ROS开发平台环境搭建与测试
- 前端模块化开发--Node基础&&WebPack模块化开发
- CNN神经网络--手写数字识别
- 关于模型预测结果好坏的几个评价指标
- SpringBoot微服务架构项目--Union社交平台
- 如何衡量前端基建的效能价值?
- mbedtls | 移植mbedtls库到STM32裸机的两种方法
- 实用小技巧 | 用socket玩转http接口
- 深度学习之人脸识别模型--FaceNet
- Java常用的设计模式
- HW防守|应急溯源分析手册汇总篇
- Python进阶(一)
- Python版本的OpenCV安装
- CVE-2020-16875:Microsoft Exchange RCE复现