In-depth understanding of the reflection mechanism in Golang

Table of contents

reflection

Classification of reflection

value reflection

type reflection

runtime reflection

compile time reflection

interface reflection

struct reflection

Common functions

value reflection

type reflection

The difference between value reflection and type reflection

struct reflection

sample code


reflection

        Reflection refers to the ability to inspect and modify objects dynamically while a program is running. In the Go language, through reflection, you can check the type of variables at runtime, obtain information about structure fields and methods, and dynamically call methods. Reflection is very useful in some scenarios that need to deal with unknown types or require dynamic operations at runtime.

Reflection can achieve the function:

1. Reflection can dynamically obtain various information of variables during program running, such as the type and category of variables.

2. If it is a structure, the information of the structure itself can also be obtained through reflection, such as the fields of the structure and the methods of the structure.

3. The value of the variable can be modified through reflection, and the associated method can be called.

Classification of reflection

value reflection

Features: Obtain the type and value of a variable through the reflect package, and perform corresponding operations.

How to use: Use functions such as ValueOf(), Type(), String() in the reflect package to obtain the type and value of the variable, and perform corresponding operations.

Function: You can get the type and value of the variable, which is convenient for type checking, converting and modifying the variable at runtime.

type reflection

Features: Obtain a type of information through the type package, including fields, methods, interfaces, etc.

How to use: Use the Type() function to obtain the type of a variable, and use functions such as FieldByName(), MethodByName(), IndirectMethodByName() to obtain information such as fields, methods, and interfaces of the type.

Function: You can obtain the structural information of the type, which is convenient for operating and calling the type at runtime.

runtime reflection

Features: Dynamically obtain type information and call methods when the program is running.

How to use: Use functions such as Interface(), Ptr(), Slice() in the reflect package to dynamically create types and objects, and call their methods.

Function: It can dynamically obtain type information and call methods when the program is running, which is convenient for realizing some advanced functions.

compile time reflection

Features: Obtain type information and call methods at compile time.

How to use: Use the AST generation tool in the go/build package to generate an executable file and perform reflection operations in it.

Function: You can obtain type information and call methods at compile time, which is convenient for implementing some advanced functions. However, due to the need to generate executable files, the performance is lower.

interface reflection

Features: Obtain type information through the interface.

How to use: Use the Interface() function in the type package to obtain a type of interface, and then use the Elem() function to obtain the specific type in the interface.

Function: You can obtain the interface information of the type, which is convenient to operate and call according to the interface type at runtime.

struct reflection

Features: Obtain type information through the structure.

How to use: Use the StructOf() function in the type package to create a structure of a specified type, and then use FieldByIndex(), FieldByName() and other functions to obtain the field information of the structure.

Function: You can obtain the structure information of the type, which is convenient for operating and calling the structure at runtime.

Common functions

TypeOf(obj): The function of this function is to obtain the type of an object and return a value of type Type. In reflection, each object has a corresponding Type, through which information such as properties and methods of the object can be obtained.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    x := 42
    fmt.Println(reflect.TypeOf(x)) // 输出:int
}

ValueOf(obj): The function of this function is to get the value of an object and return a value of type Value. In reflection, Value represents the value of an object, and the properties, methods, and other information of the object can be modified through Value.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    x := 42
    fmt.Println(reflect.ValueOf(x)) // 输出:42000 (int64)
}

New(typ): The function of this function is to create a new object according to the specified type and return a value of type Value. In reflection, we can use Type and Value to manipulate data of Struct type.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    typ := reflect.TypeOf(map[string]int{}) // 定义一个map类型的Type
    fmt.Println(typ) // 输出:map[string]int struct{}
    v := reflect.New(typ) // 创建一个新的map对象
    fmt.Println(v.Interface()) // 输出:nil (空map)
}

String(): The function of this function is to obtain the string representation of an object and return a value of type string. In reflection, we can use the String() method to get the string representation of an object.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    x := reflect.TypeOf("hello, world") // 定义一个字符串类型的Type
    fmt.Println(x) // 输出:string struct{}
    fmt.Println(x.String()) // 输出:string struct{}
}

MethodByName(object interface{}, methodName string): The function of this function is to obtain a method according to the specified object and method name, and return a value of type Method. In reflection, we can use the MethodByName() method to get a method of a structure or interface type.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    c := &struct{}{} // 定义一个结构体类型的变量c,并初始化为nil指针
    fmt.Println(reflect.TypeOf(c).MethodByName("MarshalJSON")) // 输出:func(*json.RawMessage) error struct{} (MarshalJSON method of struct{})
}

value reflection

Value reflection refers to the ability to obtain type information from a variable's value. In Golang, you can use reflect.ValueOf()functions to get the value of a variable and Type()functions to get its type.

For example:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    x := 42
    fmt.Println("Value of x:", reflect.ValueOf(x)) //输出:Value of x: 0xc00008a000 (i32)
    fmt.Println("Type of x:", reflect.TypeOf(x)) //输出:Type of x: i32
}

Define an integer variable x, and use reflect.ValueOf()the function to get its value 0xc00008a000, that is, int32the type i32. Then we used reflect.TypeOf()the function to get its type as i32

type reflection

Type reflection refers to the ability to obtain information about a variable by its type. In Golang, you can use reflect.Type()functions to get the type information of a variable. For example:

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string `json:"name"`
    Age  int32  `json:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 18}
    fmt.Println("Type of p:", reflect.TypeOf(p)) //输出:Type of p: *main.Person (struct)
}

Define a Personstruct type called , and define two fields in it: Nameand Age. Then we created a Personvariable of type pand used reflect.TypeOf()the function to get its type *main.Person (struct)

The difference between value reflection and type reflection

In Golang, both value reflection and type reflection are reflectimplemented through packages. Their difference is:

Value reflection refers to obtaining the type and value of a variable at runtime. By using reflectthe functions and types in the package, we can implement the function of value reflection. For example, you can use reflect.ValueOf()a function to get the value of a variable, and Type()a function to get its type.

Type reflection refers to obtaining the structure information or label information of a variable at runtime. By using reflectthe functions and types in the package, we can implement the function of type reflection. For example, you can use StructField()a function to get the field information of a struct, and Type()a function to get its type.

So the main difference between value reflection and type reflection is what they focus on. Value reflection focuses on the type and value of the variable, while type reflection focuses on the structure information or label information of the variable.

struct reflection

        In the Go language, a structure is a custom data type, and reflection is a mechanism for dynamically obtaining variable types and values ​​at runtime. Structure reflection refers to the mechanism of dynamically obtaining structure types and values ​​at runtime. Some advanced functions can be realized through reflection, such as converting a structure object into a string or parsing a structure object from a string.

 

sample code

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	p := Person{
		Name: "Alice",
		Age:  20,
	}

	// 获取结构体类型和值的反射对象
	t := reflect.TypeOf(p)
	v := reflect.ValueOf(p)

	// 打印结构体类型和值的相关信息
	fmt.Println("Type:", t.Name())
	fmt.Println("Kind:", t.Kind())
	fmt.Println("Value:", v)

	// 遍历结构体的字段
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)
		fmt.Printf("Field Name: %s, Field Value: %v\n", field.Name, value)
	}

	// 通过字段名称获取对应的值
	name := v.FieldByName("Name")
	fmt.Println(name.Interface())

	// 通过标签获取字段的值
	ageField := t.FieldByName("Age")
	ageTag := ageField.Tag.Get("json")
	fmt.Println(ageTag)
}

Define a Person structure, which contains two fields Name and Age. In the main function, we create a Person object p and get the reflection objects t and v of its type and value. Then, we printed the relevant information of the structure type and value, traversed the fields of the structure, and obtained the corresponding value through the field name and label.

The output is as follows:

Type: Person
Kind: struct
Value: {Alice 20}
Field Name: Name, Field Value: Alice
Field Name: Age, Field Value: 20
Alice
age

Guess you like

Origin blog.csdn.net/weixin_71646897/article/details/130783813