当前位置:网站首页>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
边栏推荐
- 海泰前沿技术|隐私计算技术在医疗数据保护中的应用
- 主数据建设的背景
- Nifi quick installation (stand-alone / cluster)
- Mapstacks: data normalization and layered color layer loading
- Memo mode - game archiving
- 畅直播|针对直播痛点的关键技术解析
- 全上链哈希游戏dapp系统定制(方案设计)
- Docker deploy mysql5.7
- What are the problems with traditional IO? Why is zero copy introduced?
- Several common command operations in win system
猜你喜欢

It was Tencent who jumped out of the job with 26k. It really wiped my ass with sandpaper. It gave me a hand

Common data model (updating)

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

微信小程序中使用vant组件

A/B测试助力游戏业务增长

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

When querying the database with Gorm, reflect: reflect flag. mustBeAssignable using unaddressable value

Limit summary (under update)

(to be optimized and modified) vivado DDR4 SDRAM (MIG) (2.2) IP core learning record

Prototype mode -- clone monster Army
随机推荐
The Google File System (GFS) learning notes
[performance tuning basics] performance tuning strategy
Undo log and redo log must be clear this time
等保备案是等保测评吗?两者是什么关系?
Prototype mode -- clone monster Army
go_ keyword
JMeter response assertion
Geek University cloud native training camp
Learn to use a new technology quickly
Shrimp skin test surface treated
Bean lifecycle flowchart
What are the problems with traditional IO? Why is zero copy introduced?
A/b test helps the growth of game business
Responsibility chain mode -- through interview
Talking about the range of data that MySQL update will lock
Curl command
Requests requests for web page garbled code resolution
Sleep revolution - find the right length of rest
浅谈MySql update会锁定哪些范围的数据
Microsoft Certification (dynamic 365) test