当前位置:网站首页>go reflect
go reflect
2022-04-23 20:43:00 【baboon_ chen】
List of articles
Reflection
Go Language provides a mechanism , Without knowing the type at compile time , Updatable variables 、 View values at runtime 、 Call methods of type , And directly operate on their layout , This mechanism is called reflection (reflection).
One 、relect.Type
1、 What is? relect.Type
?
Go
Any variable in the language containsreflect.Type
Andreflect.Value
Two parts of information .
reflect.Type
Is when declaring variablestype
, It's inGo
Is defined as an interface .
type Type interface {
Align() int
FieldAlign() int
Method(int) Method
MethodByName(string) (Method, bool)
NumMethod() int
Name() string
PkgPath() string
Size() uintptr
String() string
Kind() Kind
Implements(u Type) bool
AssignableTo(u Type) bool
ConvertibleTo(u Type) bool
Comparable() bool
Bits() int
ChanDir() ChanDir
IsVariadic() bool
Elem() Type // The value of the element that the value points to , Similar to the language level * operation . Downtime occurs when the value type is not a pointer or interface , Null pointer returns nil Of Value
Field(i int) StructField
FieldByIndex(index []int) StructField
FieldByName(name string) (StructField, bool)
FieldByNameFunc(match func(string) bool) (StructField, bool)
In(i int) Type
Key() Type
Len() int
NumField() int
NumIn() int
NumOut() int
Out(i int) Type
common() *rtype
uncommon() *uncommonType
}
2、 How to distinguish reflect.Type
( type ) And reflect.Kind
( species )?
reflect.Type.Name()
Is the type specified when declaring the variable .Go
Language is a statically typed language , Each variable has a static type , The type is determined when compiling . No matter how the value of the variable changes , The type of variable never changes . Between two different static types , It cannot be assigned ( If there is no type conversion ).
type MyInt int
var i int = 5
var j MyInt = 10
j = i // build error: cannot use i (type int) as type MyInt in assignment
reflect.Kind
yes Go
Built in types defined in ( The underlying data type ), Such as these :
type Kind uint
const (
Invalid Kind = iota // Illegal type
Bool // Boolean type
Int // signed int
Int8 // A signed 8 An integer
Int16 // A signed 16 An integer
Int32 // A signed 32 An integer
Int64 // A signed 64 An integer
Uint // Unsigned integer
Uint8 // Unsigned 8 An integer
Uint16 // Unsigned 16 An integer
Uint32 // Unsigned 32 An integer
Uint64 // Unsigned 64 An integer
Uintptr // The pointer
Float32 // Single-precision floating-point
Float64 // Double precision floating point
Complex64 // 64 Bit plural type
Complex128 // 128 Bit plural type
Array // Array
Chan // passageway
Func // function
Interface // Interface
Map // mapping
Ptr // The pointer
Slice // section
String // character string
Struct // Structure
UnsafePointer // Bottom pointer
)
Example : distinguish Type
And Kind
package main
import (
"fmt"
"reflect"
)
type MyType int
type Stu struct {
name string
score float32
}
func test1(a interface{
}) {
fmt.Printf("the type of a is: %v\n", reflect.TypeOf(a))
fmt.Printf("the kind of a is: %v\n\n", reflect.ValueOf(a).Kind())
}
func main() {
var a Stu
var b MyType
test1(a)
test1(b)
}
Output :
the type of a is: main.Stu
the kind of a is: struct
the type of a is: main.MyType
the kind of a is: int
3、 Pointer reflection
Go
When getting a reflection object from a pointer in a language program , Can pass reflect.Elem()
Method to get the type of element this pointer points to , This fetch process is called fetch element , It's equivalent to making a pointer type variable *
operation .
reflect.Elem()
The return is Type
// Elem returns a type's element type.
// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
Elem() Type
Go Of all pointer variables in the reflection of language
species
All arePtr
, But it should be noted that , Pointer variable'sType.Name()
yesnil
.
Example :
func main() {
type cat struct {
}
p := &cat{
}
typeOfCat := reflect.TypeOf(p)
fmt.Printf("type: %v\n", typeOfCat) // reflect.Type yes interface type , So it can be passed to fmtr Print
fmt.Printf("TypeName: %v, Kind: %v\n", typeOfCat.Name(), typeOfCat.Kind())
fmt.Printf("TypeName: %v, Kind: %v\n", typeOfCat.Elem().Name(), typeOfCat.Elem().Kind())
}
Output :
type: *main.cat
TypeName: , Kind: ptr
TypeName: cat, Kind: struct
4、 Structural reflection
If the reflection object is a structure , Then there are the following methods to obtain the member information in the structure :
Method | explain |
---|---|
Field(i int) StructField | Return the information of the structure field corresponding to the index according to the index , Downtime occurs when the value is not a struct or index out of bounds |
NumField() int | Returns the number of struct member fields , Downtime occurs when the type is not a struct or index out of bounds |
FieldByName(name string) (StructField, bool) | Returns the information of the structure field corresponding to the string according to the given string , When not found bool return false, Downtime occurs when the type is not a struct or index out of bounds |
FieldByIndex(index []int) StructField | When multiple members visit , according to []int The field index of each structure provided , Return the information of the field , Return zero when not found . Downtime occurs when the type is not a struct or index out of bounds |
FieldByNameFunc(match func(string) bool) (StructField,bool) | Match the required fields according to the match function , Downtime occurs when the value is not a struct or index out of bounds |
1)StructField
( Structure field )
reflect.Type
OfField()
Method returnsStructField
structure , This structure describes the member information of the structure , Through this information, we can get the relationship between members and the structure , Such as deviation 、 Indexes 、 Is it an anonymous field 、 Structural tagStructTag
etc. , And it can also be passedStructField
OfType
Field Further access to Type information of structure members .
StructField The structure is as follows :
type StructField struct {
Name string // Field name
PkgPath string // Field path
Type Type // Field reflection type object
Tag StructTag // The structure label of the field
Offset uintptr // The relative offset of the field in the structure
Index []int // Type.FieldByIndex Index value returned in
Anonymous bool // Is it an anonymous field
}
Example :
func main() {
type cat struct {
Name string
Color string
Age int
Home struct {
Adderess string
PostCode int
}
}
ins := cat{
Name: "Tom",
Color: "Dark",
Age: 5,
Home: struct{
Adderess string
PostCode int
}{
"England",
1024,
},
}
sType := reflect.TypeOf(ins)
for i:=0; i < sType.NumField(); i++ {
filed := sType.Field(i)
fmt.Printf("filedName: %s, Type: %v\n", filed.Name, filed.Type)
}
if addrType, ok := sType.FieldByName("Adderess"); ok {
fmt.Printf("Name: %s, Type: %v", addrType.Name, addrType.Type)
}
}
Output :
filedName: Name, Type: string
filedName: Color, Type: string
filedName: Age, Type: int
// Adderess Belong to Home This member
filedName: Home, Type: struct {
Adderess string; PostCode int }
2)StructTag
( Structural tag )
Structure member information
reflect.StructField
The structure of theTag
It is called structure labelStructTag
. Structure labels are additional information labels for structure fields .
type StructTag string
Format of structure label
`key1:"value1" key2:"value2"`
The structure tag consists of one or more key value pairs ; Keys and values are separated by colons , There must be no spaces after the colon , Value in double quotes ; Use a space between key value pairs .
Get the value from the structure tag
StructTag Have some methods , Can be done Tag Analysis and extraction of information , As shown below :
func (tag StructTag) Get(key string) string // according to Tag The key in gets the corresponding value .
func (tag StructTag) Lookup(key string) (value string, ok bool) // according to Tag The key , Whether the query value exists .
Example :
func test4() {
type cat struct {
Name string `json:"name" bson:"NAME"`
Color string
}
ins := cat{
Name: "Tom",
Color: "Dark",
}
sType := reflect.TypeOf(ins)
if filedName, ok := sType.FieldByName("Name"); ok {
nameJson := filedName.Tag.Get("json")
fmt.Printf("the json tag of Name is: %s\n", nameJson)
}
}
Output :
the json tag of Name is: name
Two 、relect.Value
reflect.Value
type Value struct {
typ *rtype
ptr unsafe.Pointer
flag
}
// Method :
pointer() unsafe.Pointer
Addr() Value // Returns the address of an addressable value , Similar to the language level & operation . Downtime when value is not addressable
Bool() bool // It will be worth bool Type return
Bytes() []byte // Array values in bytes []bytes Type return
runes() []rune
CanAddr() bool // Indicates whether the value is addressable
CanSet() bool // Can the return value be modified . The value is required to be addressable and exported
Call(in []Value) []Value
CallSlice(in []Value) []Value
call(op string, in []Value) []Value
Cap() int
Close()
Complex() complex128
Elem() Value // The value of the element that the value points to , Similar to the language level * operation . Downtime occurs when the value type is not a pointer or interface , Null pointer returns nil Of Value
Field(i int) Value
FieldByIndex(index []int) Value
FieldByName(name string) Value
FieldByNameFunc(match func(string) bool) Value
Float() float64 // Put the value in double precision (float64) Type return , All floats (float32、float64) All can return to
Index(i int) Value
Int() int64 // It will be worth int64 Type return , All signed integers can return , Type conversion may be required
CanInterface() bool
Interface() (i interface{
}) // It will be worth interface{} Type return , You can convert to the specified type by type assertion
InterfaceData() [2]uintptr
IsNil() bool // Whether the return value is nil. If the value type is not a channel (channel)、 function 、 Interface 、map、 A pointer or When slicing panic, Similar to the language level v== nil operation
IsValid() bool // Whether the judgment value is valid . When the value itself is illegal , return false, for example reflect Value Does not contain any value , The value is nil etc. .
IsZero() bool
Kind() Kind
Len() int
MapIndex(key Value) Value
MapKeys() []Value
MapRange() *MapIter
Method(i int) Value
NumMethod() int
MethodByName(name string) Value
NumField() int
OverflowComplex(x complex128) bool
OverflowFloat(x float64) bool
OverflowInt(x int64) bool
OverflowUint(x uint64) bool
Pointer() uintptr
Recv() (x Value, ok bool)
recv(nb bool) (val Value, ok bool)
Send(x Value)
send(x Value, nb bool) (selected bool)
Set(x Value)
SetBool(x bool)
SetBytes(x []byte)
setRunes(x []rune)
SetComplex(x complex128)
SetFloat(x float64)
SetInt(x int64)
SetLen(n int)
SetCap(n int)
SetMapIndex(key Value, elem Value)
SetUint(x uint64)
SetPointer(x unsafe.Pointer)
SetString(x string)
Slice(i int, j int) Value
Slice3(i int, j int, k int) Value
String() string // Returns the value as a string type
TryRecv() (x Value, ok bool)
TrySend(x Value) bool
Type() Type
Uint() uint64 // It will be worth uint Type return , All unsigned integers can return
UnsafeAddr() uintptr
assignTo(context string, dst *rtype, target unsafe.Pointer) Value
Convert(t Type) Value
1、 Get a specific type of value
// sclice
Index(i int) Value // Back to page i Elements , If i Crossing the border will collapse
// struct
NumField() int // Returns the number of fields
Field(i int) Value // Back to page i A field , If i Crossing the border will collapse
// map
MapIndex(key Value) Value // return key Corresponding value
// ptr
Elem() Value
// interface
// Through the first IsNil Judge whether it is not empty , If it is not empty , Re pass Elem() Get dynamic values
2、 Judge Value
Whether the value in is valid :
// *int The null pointer of
var a *int
fmt.Println("nil *int IsNil:", reflect.ValueOf(a).IsNil())
fmt.Println("nil *int IsValid:", reflect.ValueOf(nil).IsValid())
// Instantiate a structure
s := struct{
}{
}
// Try to find a non-existent field from the structure
fmt.Println(" There are no structural members IsValid:", reflect.ValueOf(s).FieldByName("").IsValid())
// Try to find a non-existent method from the structure
fmt.Println(" There is no structural method IsValid:", reflect.ValueOf(s).MethodByName("").IsValid())
// Instantiate a map
m := map[int]int{
}
// Try from map Search for a key that doesn't exist
fmt.Println(" Keys that don't exist IsValid:", reflect.ValueOf(m).MapIndex(reflect.ValueOf(3)).IsValid())
Output :
nil *int IsNil: true
nil *int IsValid: false
There are no structural members IsValid: false
There is no structural method IsValid: false
Keys that don't exist IsValid: false
3、 Create instances with type information
var a int
myType := reflect.TypeOf(a)
myIns := reflect.New(myType) // *int
myIns.Elem().SetInt(15)
fmt.Println(myIns.Type())
fmt.Println(myIns.Elem().Interface())
// Output
// *int
// 15
4、 Call functions through reflection
// Ordinary function
func add(a, b int) int {
return a + b
}
func main() {
// Wrap the function as a reflection value object
funcValue := reflect.ValueOf(add)
// constructors parameters , Pass in two integer values
paramList := []reflect.Value{
reflect.ValueOf(10), reflect.ValueOf(20)}
// Reflection calls function
retList := funcValue.Call(paramList)
// Get the first return value , Take the whole number
fmt.Println(retList[0].Int())
}
// After the call is successful , adopt retList[0] Take the first parameter of the return value , Use Int Take the integer value of the return value .
// Call(in []Value) []Value
3、 ... and 、 Three laws of reflection
1、 Reflection can " Interface type variables " Convert to " Reflection type object ".
notes : Here, reflection type refers to reflect.Type
and reflect.Value
.
TypeOf
And ValueOf
The parameter of is an empty interface type , Any variable can be passed in .
func TypeOf(i interface{
}) Type
func ValueOf(i interface{
}) Value
2、 Reflection can " Reflection type object " Convert to " Interface type variables ".
reflect.Type
It's an interface , So pass it on to fmt
The function will print the underlying data .reflect.Value
Yes interface()
Method .
// Interface returns v's value as an interface{}.
func (v Value) Interface() interface{
}
var a int
fmt.Println(reflect.ValueOf(a).Interface())
3、 If you want to modify Reflection type object
Its value must be Writable
.
Go
The language is similar tox
、x.f[1]
and*p
Any form of expression can represent a variable , But others such asx + 1
andf(2)
Is not a variable . A variable is an addressable memory space , It stores a value , And the stored value can be updated by memory address .
writability
The final decision is whether a reflective object stores the original value . For a withoutwritability
OfValue
Type variable , callSet
Method will report an error . We can go throughCanSet()
Method check areflect.Value
Type variablewritability
.CanAddr()
ExpressAddressable
, AddressableValue
Not necessarily , You also need to determine whether it can be exported . such as , Private members in a structure are not exportable (unexported field).
Example :
var a int = 3
fmt.Printf("a CanAddr: %v\n", reflect.ValueOf(a).CanAddr())
v := reflect.ValueOf(&a).Elem()
fmt.Printf("v CanAddr: %v\n", v.CanAddr())
fmt.Printf("v CanSet: %v\n", v.CanSet())
v.SetInt(1)
fmt.Println(a)
Output :
a CanAddr: false
v CanAddr: true
v CanSet: true
1
版权声明
本文为[baboon_ chen]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204210546350991.html
边栏推荐
- 高薪程序员&面试题精讲系列91之Limit 20000加载很慢怎么解决?如何定位慢SQL?
- How many hacking methods do you know?
- Syntaxerror: unexpected token r in JSON at position 0
- pikachuxss如何获取cookie靶场,返回首页总是失败
- 【PTA】L2-011 玩转二叉树
- Recognition of high-speed road signs by Matlab using alexnet
- "Meta function" of tidb 6.0: what is placement rules in SQL?
- 软件测试要怎么学?自学还是培训看完这篇文章你就懂了
- SQL: query duplicate data and delete duplicate data
- On BIM data redundancy theory
猜你喜欢
Plato Farm元宇宙IEO上线四大,链上交易颇高
On IRP from the perspective of source code
"Meta function" of tidb 6.0: what is placement rules in SQL?
缓存淘汰算法初步认识(LRU和LFU)
Latex formula
GO语言开发天天生鲜项目第三天 案例-新闻发布系统二
BMP JPEG picture to vector image contourtrace
Mathematical modeling column | Part 5: MATLAB optimization model solving method (Part I): Standard Model
[PTA] l1-002 printing hourglass
Modeling based on catiav6
随机推荐
LeetCode 1351、统计有序矩阵中的负数
Install MySQL 5.0 under Linux 64bit 6 - the root password cannot be modified
浅谈数据库设计之三大范式
bounding box iou
居家第二十三天的午饭
GO语言开发天天生鲜项目第三天 案例-新闻发布系统二
中创存储|想要一个好用的分布式存储云盘,到底该怎么选
Scrapy教程 - (2)寫一個簡單爬蟲
go slice
The construction and use of Fortress machine and springboard machine jumpserver are detailed in pictures and texts
Leetcode 74. Search two-dimensional matrix
I JS deep copy and shallow copy
MySQL进阶之常用函数
Shanghai responded that "flour official website is an illegal website": neglect of operation and maintenance has been "hacked", and the police have filed a case
LeetCode 1346、检查整数及其两倍数是否存在
[PTA] get rid of singles
LeetCode-279-完全平方数
[PTA] l2-011 play with binary tree
Implementation of mypromise
41. 缺失的第一个正数