当前位置:网站首页>golang6 反射
golang6 反射
2022-06-29 12:47:00 【一只泰迪熊】
反射的基本介绍
1)反射可以在运行时动态获取变量的各种信息, 比如变量的类型(type),类别(kind)
2)如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)
3)通过反射,可以修改变量的值,可以调用关联的方法。
4)使用反射,需要 import (“reflect”)
反射重要的函数和概念
//专门演示反射
func reflectTest01(b interface{
}) {
//通过反射获取的传入的变量的 type , kind, 值
//1. 先获取到 reflect.Type
rTyp := reflect.TypeOf(b)
fmt.Println("rType=", rTyp)
//2. 获取到 reflect.Value
rVal := reflect.ValueOf(b)
n2 := 2 + rVal.Int()
//n3 := rVal.Float()
fmt.Println("n2=", n2)
//fmt.Println("n3=", n3)
fmt.Printf("rVal=%v rVal type=%T\n", rVal, rVal)
//下面我们将 rVal 转成 interface{}
iV := rVal.Interface()
//将 interface{} 通过断言转成需要的类型
num2 := iV.(int)
fmt.Println("num2=", num2)
}
//专门演示反射[对结构体的反射]
func reflectTest02(b interface{
}) {
//通过反射获取的传入的变量的 type , kind, 值
//1. 先获取到 reflect.Type
rTyp := reflect.TypeOf(b)
fmt.Println("rType=", rTyp)
//2. 获取到 reflect.Value
rVal := reflect.ValueOf(b)
//3. 获取 变量对应的Kind
//(1) rVal.Kind() ==>
kind1 := rVal.Kind()
//(2) rTyp.Kind() ==>
kind2 := rTyp.Kind()
fmt.Printf("kind =%v kind=%v\n", kind1, kind2)
//下面我们将 rVal 转成 interface{}
iV := rVal.Interface()
fmt.Printf("iv=%v iv type=%T \n", iV, iV)
//将 interface{} 通过断言转成需要的类型
//这里,我们就简单使用了一带检测的类型断言.
//同学们可以使用 swtich 的断言形式来做的更加的灵活
stu, ok := iV.(Student)
if ok {
fmt.Printf("stu.Name=%v\n", stu.Name)
}
}
type Student struct {
Name string
Age int
}
type Monster struct {
Name string
Age int
}
func main() {
//请编写一个案例,
//演示对(基本数据类型、interface{}、reflect.Value)进行反射的基本操作
//1. 先定义一个int
var num int = 100
reflectTest01(num)
//2. 定义一个Student的实例
stu := Student{
Name : "tom",
Age : 20,
}
reflectTest02(stu)
}
反射的注意事项和细节
1)reflect.Value.Kind,获取变量的类别,返回的是一个常量
2)Type 和 Kind 的区别 Type 是类型, Kind 是类别,
Type 和 Kind 可能是相同的,也可能是不同的.
比如: var num int = 10 num 的 Type 是 int , Kind 也是 int
比如: var stu Student stu 的 Type 是 pkg1.Student , Kind 是 struct
5)通过反射的来修改变量, 注意当使用 SetXxx 方法来设置需要通过对应的指针类型来完成, 这样才能改变传入的变量的值, 同时需要使用到 reflect.Value.Elem()方
6)reflect.Value.Elem()
反射最佳实践
1)使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值
//定义了一个Monster结构体
type Monster struct {
Name string `json:"name"`
Age int `json:"monster_age"`
Score float32 `json:"成绩"`
Sex string
}
//方法,返回两个数的和
func (s Monster) GetSum(n1, n2 int) int {
return n1 + n2
}
//方法, 接收四个值,给s赋值
func (s Monster) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
}
//方法,显示s的值
func (s Monster) Print() {
fmt.Println("---start~----")
fmt.Println(s)
fmt.Println("---end~----")
}
func TestStruct(a interface{
}) {
//获取reflect.Type 类型
typ := reflect.TypeOf(a)
//获取reflect.Value 类型
val := reflect.ValueOf(a)
//获取到a对应的类别
kd := val.Kind()
//如果传入的不是struct,就退出
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
//获取到该结构体有几个字段
num := val.NumField()
fmt.Printf("struct has %d fields\n", num) //4
//变量结构体的所有字段
for i := 0; i < num; i++ {
fmt.Printf("Field %d: 值为=%v\n", i, val.Field(i))
//获取到struct标签, 注意需要通过reflect.Type来获取tag标签的值
tagVal := typ.Field(i).Tag.Get("json")
//如果该字段于tag标签就显示,否则就不显示
if tagVal != "" {
fmt.Printf("Field %d: tag为=%v\n", i, tagVal)
}
}
//获取到该结构体有多少个方法
numOfMethod := val.NumMethod()
fmt.Printf("struct has %d methods\n", numOfMethod)
//var params []reflect.Value
//方法的排序默认是按照 函数名的排序(ASCII码)
val.Method(1).Call(nil) //获取到第二个方法。调用它
//调用结构体的第1个方法Method(0)
var params []reflect.Value //声明了 []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := val.Method(0).Call(params) //传入的参数是 []reflect.Value, 返回[]reflect.Value
fmt.Println("res=", res[0].Int()) //返回结果, 返回的结果是 []reflect.Value*/
}
func main() {
//创建了一个Monster实例
var a Monster = Monster{
Name: "黄鼠狼精",
Age: 400,
Score: 30.8,
}
//将Monster实例传递给TestStruct函数
TestStruct(a)
}
边栏推荐
- Matlab fmincon precision, fmincon and quadprog error
- weserver發布地圖服務
- Don't build the wheel again. It is recommended to use Google guava open source tool class library. It is really powerful!
- Distributed cache for memcached
- ANSVC无功补偿装置在河北某购物广场中的应用
- AOSP ~ logcat persistence
- Cicd introduction [easy to understand]
- Follow me study hcie big data mining Chapter 1 Introduction to data mining module 1
- 运动App如何实现端侧后台保活,让运动记录更完整?
- Summary of binary tree exercises
猜你喜欢

Proteus simulation of buck switching power supply based on 51 single chip microcomputer

灵感收集·创意写作软件评测:Flomo、Obsidian Memo、Napkin、FlowUs

Appkey when applying for offline packaging of uniapp

mysql函数和约束

直觉与实现:Batch Normalization

如何让 Dapper 支持 DateOnly 类型

自主可控再下一城!首套国产ARTIQ架构量子计算测控系统发布

Online text filter less than specified length tool

昨天面试居然聊了半个多小时的异常处理

使用 Gerrit + Zadig 实现主干开发主干发布(含字节飞书实践)
随机推荐
Interview high concurrent, cool!! (high energy in the whole process, collection recommended)
Online text filter less than specified length tool
Koa2+better-sqlite3 to add, delete, change and query
Cisco simulator simple campus network design, final assignment difficulty
测试用例设计方法之等价类划分方法
手把手教你在windows上安装mysql8.0最新版本数据库,保姆级教学
Autonomous and controllable city! Release of the first domestic artiq architecture quantum computing measurement and control system
想做个答题类的微信小游戏?读这篇文章就够了
Follow me study hcie big data mining Chapter 1 Introduction to data mining module 1
极光 · 哈夫曼树の生成(线段树结构 非指针)(仿邻接表)
揭秘!付费会员制下的那些小心机!
Mondo rescue creates an image file (which is conducive to image damage recovery)
【毕业季】这四年一路走来都很值得——老学长の忠告
matplotlib的imshow函数显示灰度图像要设置vmin和vmax2个参数
win32版俄罗斯方块(学习MFC必不可少)
pdb符号库文件详解
Technology sharing | broadcast function design in integrated dispatching
The imshow function of Matplotlib displays grayscale images. Vmin and vmax2 parameters should be set
MySQL intercepts the string to remove duplication, and MySQL intercepts the string to remove reassembly
Deecamp2022 officially opened! Likaifu and zhangyaqin personally teach master courses 𞓜 innovation