当前位置:网站首页>Golang reflection operation collation
Golang reflection operation collation
2022-06-24 21:12:00 【The smell of tobacco】
Preface
What is reflex ? We often use it , And this noun is used badly , I won't go into details here .
In short , There is a variable of unknown type , Its type can be obtained through reflection , And can manipulate properties and methods .
Reflection is generally used as a generation tool method , For example, you need a ToString Method , To convert a variable to a string type , If there is no reflection , You need to write : ToStringInt, ToStringBool… wait , Add a method to each type . And with reflection , Just one ToString Method , No matter what type of variable it is , Just throw it to him .
about PHP For this weakly typed language , If you want to call a variable $a Of $b Method , It only needs $a->$b() that will do . And for Golang This strongly typed language can't be so casual . So the following is a brief introduction Golang Application of reflection in .
I hope that after reading the usage of reflection , At least I will not look at the relevant code in the future . Even when you need it, you can do it yourself .
Use
Golang The operations reflected in are defined in the package reflect in . This package mainly includes the following two objects :
reflect.TypeUsed to get the type information of variablesreflect.ValueUsed to operate on the value of a variable
Official document address : reflect.Typereflect.Value
Our use of reflection , It is also based on these two objects .
For the use of reflection , In fact, we usually use it , The following operations are mainly used , Most of the complex operations are hard to use for a hundred years :
- Operation of variable types and attributes
- Operation of variable methods
The following is a simple demonstration based on these two operations .
Operation of variable types and attributes
Get attribute information
In reflection , Type information through reflect.Type Object acquisition .
Access to type
u := struct {
name string
}{
}
// Get reflection object information . Both reflect.Type object
typeOf := reflect.TypeOf(u)
fmt.Println(typeOf)
// The type name of the variable User
fmt.Println(typeOf.Name())
// Get the underlying type of the variable .
// The underlying type of the base type is itself , such as int
// And all custom structures , The underlying types are struct
// All pointers , The underlying types are ptr
// golang All underlying types of are defined in reflect/type.go In file .
// It can be done by reflect.Array Constant for positioning
fmt.Println(typeOf.Kind())
however , Don't be happy too early , If the variable u Change to a pointer : u := &User{}. Using the above method, you can't get the type of the variable . Because the variable content stores the address , Therefore, the address needs to be accessed . The value taking operation method in the reflection package is : reflect.TypeOf(u).Elem(). After getting the value , It's all the same .
Not just pointers , Include : Array, Chan, Map, Ptr, Slice etc. , In fact, all the addresses are stored , Therefore, the capital needs to perform value taking operations .
Be careful , The underlying type here Kind It's very useful , When processing by reflection , There are too many user-defined types to judge , But its underlying type Kind There are only a dozen , Structures of the same underlying type can be treated in the same way .
Structure
type User struct {
Gender int
}
u := struct {
name string
Age int
Address struct {
City string
Country string
} `json:"address"`
User
}{
}
/* Get reflection object information */
typeOf := reflect.TypeOf(u)
// Number of structure fields
fmt.Println(typeOf.NumField())
// For the first 0 A field of information , return StructField object ( There is a description below this object )
// Available fields Name Etc , Include fields Type object
fmt.Println(typeOf.Field(0))
// Get the field according to the variable name
fmt.Println(typeOf.FieldByName("name"))
// For the first 2 The first structure is 0 Elements
fmt.Println(typeOf.FieldByIndex([]int{
2, 0}))
/* StructField Field object contents */
structField := typeOf.Field(2)
// Field name
fmt.Println(structField.Name)
// The accessible package name of the field
// Public fields starting with capital letters , All accessible , Therefore, the value is null
fmt.Println(structField.PkgPath)
// reflect.Type object
fmt.Println(structField.Type)
// The tag string of the field , It's what follows `` character string
// return StructTag object , There are instructions below
fmt.Println(structField.Tag)
// The offset of the field in the memory structure of the structure , byte
fmt.Println(structField.Offset)
// The index of the field in the structure
fmt.Println(structField.Index)
// Anonymous field . In structure Gender It belongs to anonymous field
fmt.Println(structField.Anonymous)
/* StructTag Label content */
tag := structField.Tag
// Gets the tag value of the specified name , If it does not exist , Returns an empty string
fmt.Println(tag.Get("json"))
// And Get The difference is , The second parameter returns whether the tag exists
// Some tags have empty strings that do not behave as undefined , You can use this method to get
fmt.Println(tag.Lookup("json"))
Array
The underlying type of slice is Slice, But the object types stored in different slices are different .
To put it bluntly , An array is actually a pointer to the first address . So to get the contents of the array elements , Just do a value operation .
l := []int{
1, 2}
typeOf := reflect.TypeOf(l)
// empty , Why is this empty? It's said , An array is a pointer
fmt.Println(typeOf.Name())
// slice
fmt.Println(typeOf.Kind())
// Get the type of array element
fmt.Println(typeOf.Elem().Kind())
fmt.Println(typeOf.Elem().Name())
If the array contains a structure , Just use it as a structure
map
m := map[string]int{
"a": 1,
}
typeOf := reflect.TypeOf(m)
// map You can print names without using values map[string]int Don't understand,
fmt.Println(typeOf.Name())
// Object underlying type . map
fmt.Println(typeOf.Kind())
// obtain map Of key The type of
fmt.Println(typeOf.Key().Kind())
// obtain map value The type of
fmt.Println(typeOf.Elem().Kind())
Get attribute value
In reflection , Operations on values , It's all through reflect.Value Object implemented , This object passes through reflect.ValueOf obtain .
meanwhile , be-all Value Object can call Interface Method , To turn it back Interface{} object , Then we can convert through type assertion .
The base type
Value of basic type , GO The corresponding method is provided , It's easy to use .
// Value of foundation type
a := int64(3)
valueOf := reflect.ValueOf(&a)
// Take the foundation type .
// Be careful , If not related , Will report a mistake . You can check the source code
// All plastic surgery , All back to int64, If you need int32, The return value can be obtained and forced to
fmt.Println(valueOf.Int())
//fmt.Println(valueOf.Float())
//fmt.Println(valueOf.Uint())
// ... wait
Structure
If it is a user-defined structure, how to get the value ? this , Always find the base type . Because all custom structures are composed of basic types .
u := struct {
Name string
Age int
}{
"xiao ming", 20}
valueOf := reflect.ValueOf(u)
fmt.Println(valueOf.Field(0).String())
Array
If it's an array ? It's also very simple.
l := []int{
1, 2, 3}
valueOf := reflect.ValueOf(l)
// Modify the value of the specified index
fmt.Println(valueOf.Elem().Index(0))
// Get array length
fmt.Println(valueOf.Elem().Len())
map
Get by reflection Map The value of , What you get is Value object , At the same time, use Value Object . After all Map Of key and value The types are not fixed .
m := map[string]string{
"a": "1",
}
valueOf := reflect.ValueOf(m)
// Gets the value of the specified index
fmt.Println(valueOf.MapIndex(reflect.ValueOf("a")))
// If the value of the specified index does not exist , Will return a kind by Invalid Of Value object
fmt.Println(valueOf.MapIndex(reflect.ValueOf("c")))
// take map size
fmt.Println(valueOf.Len())
// obtain map All of the key, return Value The object list
fmt.Println(valueOf.MapKeys())
// Traverse map Iterator used
mapIter := valueOf.MapRange()
mapIter.Next() // Iterate the pointer line to the next , Returns whether there is still data
fmt.Println(mapIter.Value())
fmt.Println(mapIter.Key())
Attribute assignment
Assignment of base type , reflect.Value Object provides related methods , Are subject to Set start .
Note here , Only variables of pointer type can be assigned . It's easy to understand , The value type is passed by copying when the method is called . Only by passing the pointer can we find the memory address of the original value and modify it .
so , Before we assign values , To be called Kind Method to judge its type , If it is not created through a pointer Value object , Must not be assigned .
All the following assignment operations , Can be linked with the value taking operation .
The base type
a := int64(3)
valueOf := reflect.ValueOf(a)
// This method is used to judge Value Whether the object can be assigned
valueOf.CanSet()
// Because it's a pointer , Therefore, you need to perform a value fetching operation
valueOf.Elem().SetInt(20)
fmt.Println(a)
Structure
The assignment of the structure is the same as the above get attribute value , Use a pointer to get Value object , Then assign a value to its base type .
One thing to pay attention to , Structure only public fields can be assigned by reflection , If assigned to a private field , It throws an exception .
u := struct {
Name string
Age int
}{
"xiao ming", 20}
valueOf := reflect.ValueOf(&u)
valueOf.Elem().Field(0).SetString("xiao hei")
fmt.Println(u)
Array
It is based on Set Methods do provide a lot , But I looked it up , How to assign values to array types ? So I saw this method :
func (v Value) Set(x Value)
This Set Method , Parameters received are Value object ? That would be it . Be careful , Set It is a direct replacement , Instead of adding .
l := []int{
1, 2, 3}
valueOf := reflect.ValueOf(&l)
// Create an array for later assignment
// Be careful , The array type should be the same
setValueOf := reflect.ValueOf([]int{
4, 5})
valueOf.Elem().Set(setValueOf)
fmt.Println(l)
// Modify the value of the specified index
// Through the pointer , Get the value of the specified index , Assign a value
valueOf.Elem().Index(0).SetInt(9)
fmt.Println(l)
map
m := map[string]string{
"a": "1",
}
valueOf := reflect.ValueOf(&m)
// To assign to key Set up
valueOf.Elem().SetMapIndex(reflect.ValueOf("b"), reflect.ValueOf("2"))
fmt.Println(m)
Create a null value Value
In addition to the above assignment operation , There is also a way of not having to judge the object type , By means of New, You can create a null value of the same type Value object , What is returned is a pointer Value type .
The benefits of this operation are , In use , There is no need to judge the object type at all .
a := int64(3)
// Create a content of the same type . It returns a pointer
fmt.Println(reflect.New(reflect.TypeOf(a)).Elem())
Operation of variable methods
Common method
The common method refers to the method not attached to the structure .
func add(a, b int) int {
return a + b
}
func main() {
valueOf := reflect.ValueOf(add)
// constructors parameters
paramList := []reflect.Value{
reflect.ValueOf(2), reflect.ValueOf(3)}
// Call function . Return to one Value Array
retList := valueOf.Call(paramList)
// Get the return value
fmt.Println(retList[0].Int())
}
Structure method
Get method information
Here we need to pay attention to , Structure pointers and objects have different numbers of methods , Specific to see : https://hujingnb.com/archives/348
type User struct {
Name string
}
func (u User) GetName() string {
return u.Name
}
func (u *User) SetName(name string) {
u.Name = name
}
func main() {
u := User{
}
typeOf := reflect.TypeOf(&u)
// Gets the number of methods in the structure . Private methods are not available
fmt.Println(typeOf.NumMethod())
// For the first 0 A way , return Method object . Let's introduce
fmt.Println(typeOf.Method(0))
// Get... Based on the method name , return Method object
fmt.Println(typeOf.MethodByName("GetName"))
/* Method object */
setNameFunc, _ := typeOf.MethodByName("GetName")
// Method name
fmt.Println(setNameFunc.Name)
// Method signature
fmt.Println(setNameFunc.Type)
fmt.Println(setNameFunc.Index)
// The accessible package name of the field . Public method is empty
fmt.Println(setNameFunc.PkgPath)
}
Method call
type User struct {
Name string
}
func (u User) GetName() string {
return u.Name
}
func (u *User) SetName(name string) {
u.Name = name
}
func main() {
u := User{
}
valueOf := reflect.ValueOf(&u)
// Gets the number of methods in the structure . Private methods are not available
fmt.Println(valueOf.NumMethod())
// For the first 0 A way , return Method object . Let's introduce
fmt.Println(valueOf.Method(0))
// Get... Based on the method name , return Method object
fmt.Println(valueOf.MethodByName("GetName"))
/* Method object */
setNameFunc := valueOf.MethodByName("SetName")
// Calling method
params := []reflect.Value{
reflect.ValueOf("xiao ming")}
setNameFunc.Call(params)
// At this point, the value of the object has changed
fmt.Println(u)
// The return value of the receiving method
getNameFunc := valueOf.MethodByName("GetName")
fmt.Println(getNameFunc.Call([]reflect.Value{
}))
}
Original address : https://hujingnb.com/archives/676
边栏推荐
- Minimum cost and maximum flow (template question)
- 虚拟化是什么意思?包含哪些技术?与私有云有什么区别?
- Subnet partition operation
- Use the transparent [x] cross button image in the dialog
- The four stages of cloud computing development have finally been clarified
- Nifi quick installation (stand-alone / cluster)
- 伯克利、MIT、剑桥、DeepMind等业内大佬线上讲座:迈向安全可靠可控的AI
- Rip/ospf protocol notes sorting
- Shell script
- Markdown use
猜你喜欢

Realization of truth table assignment by discrete mathematical programming

Am, FM, PM modulation technology

Sleep revolution - find the right length of rest

红象云腾完成与龙蜥操作系统兼容适配,产品运行稳定
[email protected] -Perfmon metric collector listener steps"/>JMeter installation plug-in, adding [email protected] -Perfmon metric collector listener steps

Network flow 24 questions (round table questions)

Sequential stack traversal binary tree

After 5 months' test, it took 15K to come for an interview. When I asked, it was not worth even 5K. It was really

Adding subscribers to a list using mailchimp's API V3

After a few years in the testing industry, do you still know a little?
随机推荐
海泰前沿技术|隐私计算技术在医疗数据保护中的应用
Nifi quick installation (stand-alone / cluster)
JUnit unit test
伯克利、MIT、劍橋、DeepMind等業內大佬線上講座:邁向安全可靠可控的AI
刚购买了一个MYSQL数据库,提示已有实例,控制台登录实例要提供数据库账号,我如何知道数据库账号。
Rename and delete files
I feel that I am bald again when I help my children with their homework. I feel pity for my parents all over the world
Appium desktop introduction
Camera rental management system based on qt+mysql
Typescript syntax
Web automation: summary of special scenario processing methods
Background operation retry gave up; KeeperErrorCode = ConnectionLoss
VIM usage
传统的IO存在什么问题?为什么引入零拷贝的?
[performance tuning basics] performance tuning standards
Sleep revolution - find the right length of rest
(to be optimized and modified) vivado DDR4 SDRAM (MIG) (2.2) IP core learning record
Requests requests for web page garbled code resolution
JMeter response assertion
Introduction to interval DP