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 name
  • PkgPath: Field path
  • Type: Field reflection type object
  • Tag: Structure label of a field
  • Offset: Relative offset of a field in a structure
  • IndexThe index value returned in: type. FieldByIndex
  • Anonymous: 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