Article number originated in public address: Michael mo coding 】 【 mp.weixin.qq.com/s/F8yZyqC5U…
Later, I will use Go language to write ORM framework from zero to one. At present, I will talk about the technology used. We can look forward to it and pay attention to maimo Coding to understand the latest situation.
directory
- Concept of reflection
- Reflect the package
- Reflection Type and Kind
- Reflection Type (Type) used
- Reflection type object (TypeOf) used
- Structure object
- variable
- constant
- Pointer to the
- Reflection gets the member type of the structure
- Describes the structField structure
- demo
- (Struct Tag)
- Label concept
- The tag format
- Labeling method
- Label the demonstration
- Small talk
- Welcome to join my official account [Maimocoding] pk big factory together
Basic concept of reflection
Reflection allows us to explore the type information and memory structure of objects at runtime, which makes up for the dynamic behavior of static languages to some extent. At the same time, reflection is an important means to realize metaprogramming.
As with C data structures, the Go object header does not have a type pointer, and by itself cannot tell you anything about the type at run time. All the information required for reflection operations is derived from interface variables. In addition to storing its own type, interface variables also store the type data of the actual object.
The Go language provides a mechanism for updating and checking the value of a variable at run time, calling the method of the variable, and the inherent operations that the variable supports, but not knowing the exact type of the variable at compile time. This mechanism is called reflection. Reflection also allows us to treat the type itself as a first class value type.
The Go program’s reflection system cannot obtain all types of information in an executable file space or a package. It needs to scan the source code using the corresponding lexicon, syntax parser and abstract syntax tree (AST) in the standard library to obtain this information.
The Go language provides the Reflect package to access the program’s reflection information.
Reflect the package
Reflection in Go is provided by the Reflect package, which defines two important types, Type and Value, retrieved by the reflect.typeof and Reflect.valueof functions, respectively.
func TypeOf(i interface{}) Type
func ValueOf(i interface{}) Value
Copy the code
These two reflection entry functions will convert any incoming object to the interface type.
When dealing with types, you need to distinguish between Type and Kind. The former represents real types (static types), the latter represents their infrastructure (underlying structure) categories, and next, uncover Type and Kind.
Reflection Type and Kind
When using reflection, you first need to understand the meaning of Type and Kind. In reflection, if you want to distinguish between large types, use Kind first, which is more granular than Type. For example, Map, Slice, and Chan are all reference types, but if you want to distinguish them, you can use Kind because they are different. They are Map, Slice, and Chan.
A Kind refers to the Kind to which the object belongs, as defined in the Reflect package:
type Kind uint
const (
Invalid Kind = iota // Illegal type
Bool / / the Boolean
Int // Signed integer
Int8 // Signed 8-bit integer type
Int16 // Signed 16-bit integer type
Int32 // Signed 32-bit integer type
Int64 // Signed 64-bit integer type
Uint // Unsigned integer type
Uint8 // Unsigned 8-bit integer type
Uint16 // Unsigned 16-bit integer type
Uint32 // Unsigned 32-bit integer type
Uint64 // Unsigned 64-bit integer type
Uintptr / / pointer
Float32 // Single-precision floating point number
Float64 // Double precision floating point number
Complex64 // The 64-bit complex number type
Complex128 // 128-bit complex number type
Array / / array
Chan / / channel
Func / / function
Interface / / interface
Map / / map
Ptr / / pointer
Slice / / section
String / / string
Struct / / structure
UnsafePointer // The underlying pointer
)
Copy the code
Reflection Type (Type) used
Structure object
Example:
package main
import (
"fmt"
"reflect"
)
type Turbo struct{}func main(a) {
// Initializes the struct object
var a = Turbo{}
// Get the type object of the a structure
types := reflect.TypeOf(a)
// Get the name and type of the reflection type object
fmt.Println(types.Name(), types.Kind())
}
Copy the code
Running results:
Turbo struct
Copy the code
Code description:
- the first13Line: initializationstructObject A - th15Line: Gets the type object of the A structure - the first17Line: Outputs the name and type of the reflection type objectCopy the code
variable
Example:
package main
import (
"fmt"
"reflect"
)
func main(a) {
var cost int
types := reflect.TypeOf(cost)
fmt.Println(types.Name(),types.Kind())
}
Copy the code
Running results:
int int
Copy the code
Code description:
- the first9Line: Define oneintType of variable A - first10Line: getconstThe variabletypeType - the first11Line: Outputs the name and type of the reflection type objectCopy the code
constant
Example:
package main
import (
"fmt"
"reflect"
)
type Enum int
const (
cost Enum = 1
)
func main(a) {
types := reflect.TypeOf(cost)
fmt.Println(types.Name(),types.Kind())
}
Copy the code
Running results:
Enum int
Copy the code
Code description:
- the first8Line: Defines an Enum type - the first10Line: Initializes a variable cost - number of type Enum13Line: Gets the type object of variable cost - the first14Line: Outputs the name and type of the reflection type objectCopy the code
Pointer to the
When a Go program gets a reflection object from a pointer, it can use the reflect.elem () method to get the element type to which the pointer points.
Example:
package main
import (
"fmt"
"reflect"
)
type Turbo struct{}func main(a) {
// Initializes the struct object
var a = &Turbo{}
// Get the type object of the a structure
types := reflect.TypeOf(a)
if types.Kind() == reflect.Ptr {
elem := types.Elem()
// Get the name and type of the reflection type object
fmt.Println(elem.Name(), elem.Kind())
}
}
Copy the code
Running results:
Turbo struct
Copy the code
Code description:
- the first8Line: Define onestructType object - first12Line: Instantiate the Turbo struct object - first13Line: Gets the type object of the a structure, types - no15Line: Checks whether the type of types is a pointer16Line: Gets the type element to which the pointer points - first18Line: Gets the name and type of the reflection type objectCopy the code
Reflection gets the member type of the structure
When the reflect.typeof () function is used in Go, the attribute of the member variable can be obtained by reflecting Field() or NumField() in reflect.type if its Type is struct Type. Refer to the table below for specific methods:
The Field(I) method is used to obtain the details of a Field in the structure. Since its bottom layer is composed of StructField structure, the structure is composed of StructField structure first.
Describes the structField structure
StructField has the following structure:
type StructField struct {
Name string / / the field name
PkgPath string // Field path
Type Type // Field reflection type object
Tag StructTag // The structure tag of the field
Offset uintptr // The relative offset of the fields in the structure
Index []int // The index value returned in type. FieldByIndex
Anonymous bool // Whether it is an anonymous field
}
Copy the code
Name
: Field namePkgPath
: Field pathType
: Field reflection type objectTag
: Structure label of a fieldOffset
: Relative offset of a field in a structureIndex
The index value returned in: type. FieldByIndexAnonymous
: Indicates whether the field is anonymous
demo
The following examples form a body of knowledge connected to obtaining structure member types through reflection.
package main
import (
"fmt"
"reflect"
)
type Turbo struct {
Name string
Age int
}
func main(a) {
var turbo = &Turbo{
Name: "Michael mo coding",
Age : 1,
}
types := reflect.TypeOf(turbo)
// Check whether it is a pointer object
if types.Kind() == reflect.Ptr {
// Use the elem() method to get the object to which the pointer points
types = types.Elem()
}
for i := 0; i < types.NumField(); i++ {
tf := types.Field(i)
// Get the field name
fmt.Printf("Field name :%v, field type :%v\n" , tf.Name, tf.Type)
// Determine whether the field is anonymous
fmt.Printf("Field name :%v is an anonymous field? - %v\n", tf.Name, tf.Anonymous)
fmt.Printf("Field name :%v, its position in the structure :%v\n", tf.Name, tf.Index)
fmt.Println("-- -- -- -- -- -- -- --")}if sf, ok := types.FieldByName("Class"); ! ok { fmt.Println("This field does not exist")}else {
fmt.Printf("The field name is :%v", sf.Name)
}
}
Copy the code
Running results:
Field Name :Name, type:stringIs Name an anonymous field? -falseColumn Name :Name, its position in the structure :[0-------- field name :Age, field type:intIs Age an anonymous field? -falseField name :Age, its position in the structure :[1] -------- The field does not existCopy the code
(Struct Tag)
Structure tag concept
The reflect.Type method is used to retrieve structure member information. The tags in the reflect.StructField structure are called structtags. Structure tags are additional information tags for structure fields.
Object Relational Mapping (ORM) systems, for example, use structure tags.
Structure label format
Tag The existence of a Tag in a structure:
type Turbo struct {
Name string `json:name`
Age int `json:age`
}
Copy the code
Structure labeling method
The Go language provides two ways to obtain the Tag of a field. One is to obtain the corresponding value according to the key in the Tag, and the other is to query whether the value exists according to the key in the Tag.
func (tag StructTag) Get(key string) string
: Gets the corresponding value based on the key in the Tag, for examplekey1:"value1" key2:"value2"
You can pass “key1” to get “value1”.func (tag StructTag) Lookup(key string) (value string, ok bool)
: Queries whether the value exists according to the key in the Tag.
Structure tag demo
package main
import (
"fmt"
"reflect"
)
type Turbo struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main(a) {
var turbo = &Turbo{
Name: "Michael mo coding",
Age: 1,
}
types := reflect.TypeOf(turbo)
// Check whether it is a pointer object
if types.Kind() == reflect.Ptr {
// Use the elem() method to get the object to which the pointer points
types = types.Elem()
}
for i := 0; i < types.NumField(); i++ {
tf := types.Field(i)
if tag, ok := tf.Tag.Lookup("json"); ok {
fmt.Printf("Field name :%v, its additional constraint :%v\n", tf.Name, tag)
}
}
for i := 0; i < types.NumField(); i++ {
if tf, ok := types.FieldByName("Name"); ok {
tag := tf.Tag.Get("json")
fmt.Printf("Field name :%v, its additional constraint :%v\n", tf.Name, tag)
}
}
}
Copy the code
Results show:
Field Name :Name additional constraint :Name Field Name :Age Additional constraint :Name Field Name :Name Additional constraint :Name Field Name :Name Additional constraint :NameCopy the code
Small talk
- After reading the article, oneself is not and the cp rate of reflection has increased again
- I’m Maimo, welcome to talk to me
If you think the article is well written, please click 👍 to encourage you
Welcome to join my official account [Maimocoding] pk big factory together
Welcome to Maimocoding