当前位置:网站首页>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)
- Wechat applet custom tabbar
- Shell script
- The four stages of cloud computing development have finally been clarified
- Bean lifecycle flowchart
- Pytest test framework II
- Network flow 24 questions (round table questions)
- Berkeley, MIT, Cambridge, deepmind and other industry leaders' online lectures: towards safe, reliable and controllable AI
- Limit summary (under update)
- Leetcode (455) - distribute cookies
猜你喜欢

Interpreter mode -- formulas for dating

Basic operation of sequence table

虚拟化是什么意思?包含哪些技术?与私有云有什么区别?

Basic database syntax learning

Berkeley, MIT, Cambridge, deepmind and other industry leaders' online lectures: towards safe, reliable and controllable AI

After idea installs these plug-ins, the code can be written to heaven. My little sister also has to arrange it

JMeter response assertion

伯克利、MIT、剑桥、DeepMind等业内大佬线上讲座:迈向安全可靠可控的AI

The difference between RPC and restful

Am, FM, PM modulation technology
随机推荐
Curl command
Record a deletion bash_ Profile file
[multi thread performance tuning] multi thread lock optimization (Part 1): optimization method of synchronized synchronization lock
Static routing job
红象云腾完成与龙蜥操作系统兼容适配,产品运行稳定
Prototype mode -- clone monster Army
Freshman girls' nonsense programming is popular! Those who understand programming are tied with Q after reading
Talking about the range of data that MySQL update will lock
Reflection - class object function - get method (case)
Memo mode - game archiving
Mapstacks: data normalization and layered color layer loading
Enjoy yuan mode -- a large number of flying dragons
Procedural life: a few things you should know when entering the workplace
Pytest test framework II
Packaging_ Conversion between basic type and string type
Dx12 engine development course progress - where does this course go
(to be optimized and modified) vivado DDR4 SDRAM (MIG) (2.2) IP core learning record
Realization of truth table assignment by discrete mathematical programming
Steps of JMeter performance test
Rip/ospf protocol notes sorting