当前位置:网站首页>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
边栏推荐
- [AI vision · quick review of NLP natural language processing papers today, issue 31] Fri, 15 APR 2022
- Opencv -- yoact case segmentation model reasoning
- 无线键盘全国产化电子元件推荐方案
- STM32上μC/Shell移植与应用
- 第四章 --- 了解标准设备文件、过滤器和管道
- Nel ASA: her ø Ya facility in Norway officially opened
- [AI vision · quick review of today's sound acoustic papers, issue 3] wed, 20 APR 2022
- 指纹Key全国产化电子元件推荐方案
- KVM error: Failed to connect socket to ‘/var/run/libvirt/libvirt-sock‘
- 单极性非归零NRZ码、双极性非归零NRZ码、2ASK、2FSK、2PSK、2DPSK及MATLAB仿真
猜你喜欢
随机推荐
Express middleware ② (classification of Middleware)
Why recommend you to study embedded
Inverse system of RC low pass filter
RC低通滤波器的逆系统
IEEE Transactions on Systems, Man, and Cybernetics: Systems(TSMC)投稿须知
Matlab reads multiple fig graphs and then combines them into one graph (in the form of sub graph)
2020 is coming to an end, special and unforgettable.
Jetpack 之 LifeCycle 组件使用详解
Detailed explanation of life cycle component of jetpack
LabVIEW 小端序和大端序区别
Xiaohongshu was exposed to layoffs of 20% as a whole, and the internal volume among large factories was also very serious
Introduction to Cortex-M3 register set, assembly language and C language interface
针对NFT的网络钓鱼
为什么推荐你学嵌入式
【论文阅读】【3d目标检测】point transformer
【测绘程序设计】坐标方位角推算神器(C#版)
Single chip microcomputer serial port data processing (1) -- serial port interrupt sending data
補:注解(Annotation)
Unipolar NRZ code, bipolar NRZ code, 2ASK, 2FSK, 2PSK, 2DPSK and MATLAB simulation
智能电子秤全国产化电子元件推荐方案