当前位置:网站首页>Go reflection rule
Go reflection rule
2022-04-23 04:33:00 【Heavy dust】
Go The law of reflection
Reflection is Go One of the more important features of language , Although not common in most applications and services , But many frameworks rely on Go The reflection mechanism of language realizes some dynamic functions . As a static language ,Golang It's very simple in design , So in fact, there is no strong expression ability in grammar , however Go What language offers us reflect
The dynamic features provided by the package can make up for some of its syntactic disadvantages .
reflect
The reflection ability of runtime is realized , To be able to make Golang Programs that operate on different types of objects , We can use the functions in the package TypeOf
From static type interface{}
Get the dynamic type information from ValueOf
Get the runtime representation of the data , With these two functions and other tools in the package, we can get more powerful expressive power .
summary
stay go In language , The key to reflection is reflect
package , Enables programs to manipulate different types of objects . among , In the reflection package, there are two very important type and function , The two functions are :
reflect.TypeOf
- Can get information about the type of objectreflect.ValueOf
- Can get the data of the object
The two types are reflect.Type
and reflect.Value
, They correspond to functions one by one :
The law of reflection
Runtime reflection is a way for a program to check its own structure during runtime , It is Metaprogramming A kind of , But the flexibility it brings is also a double-edged sword , Excessive use of reflection will make our program logic difficult to understand and slow , We will introduce in this section Go The three laws of language reflection , This can help us better understand the role of reflection .
- Reflection objects can be reflected from interface values ;
- The interface value can be reflected from the reflection object ;
- To modify the reflection object , Its value must be settable ;
First rule
The first law of reflection is , We can Go Interface type variables in the language are converted to reflection objects , As mentioned above reflect.TypeOf
and reflect.ValueOf
That's the two most important ways to accomplish this transformation , If we think Go There are two differences between types and reflective types in language 『 The world 』 Words , So these two ways are bridges between the two worlds .
Let's briefly introduce the functions of these two methods through the following examples , among TypeOf
Gets the variable author
The type of string
and ValueOf
Get the value of the variable draven
, If we know the type and value of a variable , So that means we have all the information about this variable .
package main
import (
"fmt"
"reflect"
)
func main() {
author := "draven"
fmt.Println("TypeOf author:", reflect.TypeOf(author))
fmt.Println("ValueOf author:", reflect.ValueOf(author))
}
$ go run main.go
TypeOf author: string
ValueOf author: draven
From the type of variable, we can get the method that the current type can execute Method
And the interface implemented by the current type ;
- For structures , You can get the number of fields and get the fields by subscript and field name
StructField
; - For hash tables , Can get the hash table
Key
type ; - For functions or methods , You can get the types of input parameters and return values ;
- …
To make a long story short , Use TypeOf
and ValueOf
To be able to Go The variables in the language are converted into reflection objects , At this time, we can get almost all the data and operations related to the current type , Then you can use these runtime structures to dynamically execute some methods .
Many readers may be confused by this subtitle , Why from Interface To reflect objects , If called directly
reflect.ValueOf(1)
, It seems to be from the basic typeint
To the reflection type , howeverTypeOf
andValueOf
The input parameters of the two methods are actuallyinterface{}
type .We've been in before Function call In this section ,Go Language function calls are value passing , Variables are typed before method calls , That is to say
int
The basic variable of type is converted tointerface{}
type , That's the first rule, from interfaces to reflective objects .
The second rule
Now that we can convert a variable of an interface type to a reflection object type , Then you also need some other methods to restore the reflection object to a variable of interface type ,reflect
Medium Interface
The way to do it :
But call Interface
Methods we can only get interface{}
Interface variables of type , If you want to restore it to its original type, you need to go through a forced type conversion , As shown below :
v := reflect.ValueOf(1)
v.Interface{
}.(int)
The process from the reflective object to the interface value is the mirror process from the interface value to the reflective object , Both processes need to go through two transformations :
- From interface value to reflection object :
- Type conversion from basic type to interface type ;
- Conversion from interface type to reflection object ;
- From reflection object to interface value :
- Convert reflection object to interface type ;
- Change to the original type by explicit type conversion ;
Of course, not all variables need type conversion , If it is interface{}
Type of , So it doesn't really need to be typed , For most variables , The process of type conversion is often implicit , Only when we need to convert the reflection object back to the basic type, we need to do the conversion operation of display .
The third rule
Go The last rule of language reflection is related to whether values can be changed , If we want to update one reflect.Value
, Then the value it holds must be updatable , Suppose we have the following code :
func main() {
i := 1
v := reflect.ValueOf(i)
v.SetInt(10)
fmt.Println(i)
}
$ go run reflect.go
panic: reflect: reflect.flag.mustBeAssignable using unaddressable value
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x82, 0x1014c0)
/usr/local/go/src/reflect/value.go:247 +0x180
reflect.flag.mustBeAssignable(...)
/usr/local/go/src/reflect/value.go:234
reflect.Value.SetInt(0x100dc0, 0x414020, 0x82, 0x1840, 0xa, 0x0)
/usr/local/go/src/reflect/value.go:1606 +0x40
main.main()
/tmp/sandbox590309925/prog.go:11 +0xe0
Running the above code causes the program to panic And report reflect: reflect.flag.mustBeAssignable using unaddressable value
error , If you think about it carefully, you can actually find out the cause of the mistake ,Go Linguistic Function call It's all about value transmission , So the reflection object we get has nothing to do with the initial variable , No variables hold the copied values , So modifying it directly can lead to a crash .
If we want to modify the original variables, we can only use the following method , First, through reflect.ValueOf
Get the variable pointer , And then through Elem
Method to get the variable pointed to by the pointer and call SetInt
Method to update the value of a variable :
func main() {
i := 1
v := reflect.ValueOf(&i)
v.Elem().SetInt(10)
fmt.Println(i)
}
$ go run reflect.go
10
This kind of getting pointer corresponds to reflect.Value
And pass Elem
Method roundabout way to get variables that can be set , This complicated process is mainly due to Go Language function calls are value passing , We can interpret the above code as :
func main() {
i := 1
v := &i
*v = 10
}
If you can't operate directly i
A variable modifies the value it holds , We can only get i
Variable address and use *v
Modify the whole tree stored in the address .
版权声明
本文为[Heavy dust]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230413460324.html
边栏推荐
- Go反射—Go语言圣经学习笔记
- Brushless motor drive scheme based on Infineon MCU GTM module
- [AI vision · quick review of robot papers today, issue 31] Fri, 15 APR 2022
- C语言: 指针的进阶
- AWS EKS添加集群用户或IAM角色
- 第四章 --- 了解标准设备文件、过滤器和管道
- 补充番外14:cmake实践项目笔记(未完待续4/22)
- PHP export excel table
- Gut liver axis: host microbiota interaction affects hepatocarcinogenesis
- Interaction of diet gut microbiota on cardiovascular disease
猜你喜欢
AWS EKS 部署要点以及控制台与eksctl创建的差异
STM32上μC/Shell移植与应用
win10, mysql-8.0.26-winx64.zip 安装
Supplément: annotation
阿里云IoT流转到postgresql数据库方案
Introduction to Cortex-M3 register set, assembly language and C language interface
【论文阅读】【3d目标检测】Improving 3D Object Detection with Channel-wise Transformer
Unipolar NRZ code, bipolar NRZ code, 2ASK, 2FSK, 2PSK, 2DPSK and MATLAB simulation
【论文阅读】【3d目标检测】Voxel Transformer for 3D Object Detection
Coinbase:关于跨链桥的基础知识、事实和统计数据
随机推荐
【Echart】echart 入门
Go反射法则
Express中间件①(中间件的使用)
Leetcode->1 两数之和
重剑无锋,大巧不工
电钻、电锤、电镐的区别
Cortex-M3寄存器组、汇编语言与C语言的接口介绍
Microbial neuroimmune axis -- the hope of prevention and treatment of cardiovascular diseases
Go反射—Go语言圣经学习笔记
MYSQL50道基础练习题
国外LEAD,联盟经理常见问答
华为机试--高精度整数加法
Set classic topics
【时序】基于 TCN 的用于序列建模的通用卷积和循环网络的经验评估
Summary of Android development posts I interviewed in those years (attached test questions + answer analysis)
RC低通滤波器的逆系统
Set经典小题目
Go 语言中的 logger 和 zap 日志库
[mapping program design] coordinate azimuth calculation artifact (version C)
针对NFT的网络钓鱼