Home >Backend Development >Golang >Does go language have reflection?
Go language has reflection. The Go language provides a mechanism to update and check the value of variables, call methods of variables, and intrinsic operations supported by variables at runtime, but the specific types of these variables are not known at compile time. This mechanism is called reflection. Reflection in the Go language is supported by the reflect package, which defines two important types: Type and Value. Any interface value in reflection can be understood as consisting of two parts: reflect.Type and reflect.Value.
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
The Go language provides a mechanism to update and check the value of variables, call methods of variables, and intrinsic operations supported by variables at runtime, but the specific types of these variables are not known at compile time. This mechanism is called reflection. Reflection also allows us to treat the type itself as a first-class value type.
Reflection in go language
Reflection refers to the ability to access and modify the program itself during the running of the program. The program is compiled when Variables are converted into memory addresses, variable names are not written into the executable part by the compiler, and the program cannot obtain its own information when running the program.
Languages that support reflection can integrate the reflection information of variables, such as field names, type information, structure information, etc., into the executable file during program compilation, and provide an interface for the program to access the reflection information, so that Reflection information about types can be obtained during program runtime and have the ability to modify them.
The C/C language does not support the reflection function and can only provide very weakened program runtime type information through typeid; languages such as Java and C# all support complete reflection functions; dynamic languages such as Lua and JavaScript, due to their The syntax itself allows the code to access the program's own value and type information at runtime, so no reflection system is needed.
The reflection system of Go language program cannot obtain all type information in an executable file space or a package. It needs to use the corresponding lexical, syntax parser and abstract syntax tree (AST) in the standard library. ) to obtain this information after scanning the source code.
Go language provides the reflect package to access the reflection information of the program.
reflect package
Reflection in the Go language is supported by the reflect package, which defines two important types: Type and Value Any interface value can be understood in reflection as consisting of two parts, reflect.Type and reflect.Value, and the reflect package provides two functions, reflect.TypeOf and reflect.ValueOf, to obtain the Value and Type of any object.
Reflected type object (reflect.Type)
In a Go language program, use the reflect.TypeOf() function to obtain any value Type object (reflect.Type), the program can access the type information of any value through the type object. The following is an example to understand the process of obtaining the type object:
package main import ( "fmt" "reflect" ) func main() { var a int typeOfA := reflect.TypeOf(a) fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
The running results are as follows:
The code description is as follows:
Line 9 defines a variable of type int.
In line 10, the type object typeOfA of variable a is obtained through reflect.TypeOf(), and the type is reflect.Type().
In line 11, through the member function of the typeOfA type object, the type name of the typeOfA variable can be obtained respectively int, and the type (Kind) is int.
Type and Kind of reflection
When using reflection, you need to first understand the type The difference between (Type) and kind (Kind). In programming, the most commonly used type is type, but in reflection, when a large variety of types needs to be distinguished, kind (Kind) is used. For example, when you need to uniformly judge pointers in types, it is more convenient to use kind (Kind) information.
1) Definition of reflection type (Kind)
The type (Type) in Go language program refers to the system’s native data type, such as int, string, bool , float32 and other types, as well as types defined using the type keyword, the names of these types are the names of the types themselves. For example, when using type A struct{} to define a structure, A is the type of struct{}.
Kind refers to the type of object, which is defined as follows in the reflect package:
type Kind uint const ( Invalid Kind = iota // 非法类型 Bool // 布尔型 Int // 有符号整型 Int8 // 有符号8位整型 Int16 // 有符号16位整型 Int32 // 有符号32位整型 Int64 // 有符号64位整型 Uint // 无符号整型 Uint8 // 无符号8位整型 Uint16 // 无符号16位整型 Uint32 // 无符号32位整型 Uint64 // 无符号64位整型 Uintptr // 指针 Float32 // 单精度浮点数 Float64 // 双精度浮点数 Complex64 // 64位复数类型 Complex128 // 128位复数类型 Array // 数组 Chan // 通道 Func // 函数 Interface // 接口 Map // 映射 Ptr // 指针 Slice // 切片 String // 字符串 Struct // 结构体 UnsafePointer // 底层指针 )
Map, Slice, and Chan are reference types and are similar to pointers in use, but in The type constant definition still belongs to an independent type and does not belong to Ptr. The structure defined by type A struct{} belongs to Struct type, and *A belongs to Ptr.
2) Get the type name and type from the type object
The reflection acquisition method corresponding to the type name in the Go language is the Name() method in reflect.Type , returns a string representing the type name; the type attribute (Kind) uses the Kind() method in reflect.Type, and returns a constant of the reflect.Kind type.
下面的代码中会对常量和结构体进行类型信息获取。
package main import ( "fmt" "reflect" ) // 定义一个Enum类型 type Enum int const ( Zero Enum = 0 ) func main() { // 声明一个空结构体 type cat struct { } // 获取结构体实例的反射类型对象 typeOfCat := reflect.TypeOf(cat{}) // 显示反射类型对象的名称和种类 fmt.Println(typeOfCat.Name(), typeOfCat.Kind()) // 获取Zero常量的反射类型对象 typeOfA := reflect.TypeOf(Zero) // 显示反射类型对象的名称和种类 fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
运行结果如下:
代码说明如下:
第 17 行,声明结构体类型 cat。
第 20 行,将 cat 实例化,并且使用 reflect.TypeOf() 获取被实例化后的 cat 的反射类型对象。
第 22 行,输出 cat 的类型名称和种类,类型名称就是 cat,而 cat 属于一种结构体种类,因此种类为 struct。
第 24 行,Zero 是一个 Enum 类型的常量。这个 Enum 类型在第 9 行声明,第 12 行声明了常量。如没有常量也不能创建实例,通过 reflect.TypeOf() 直接获取反射类型对象。
第 26 行,输出 Zero 对应的类型对象的类型名和种类。
指针与指针指向的元素
Go语言程序中对指针获取反射对象时,可以通过 reflect.Elem() 方法获取这个指针指向的元素类型,这个获取过程被称为取元素,等效于对指针类型变量做了一个*操作,代码如下:
package main import ( "fmt" "reflect" ) func main() { // 声明一个空结构体 type cat struct { } // 创建cat的实例 ins := &cat{} // 获取结构体实例的反射类型对象 typeOfCat := reflect.TypeOf(ins) // 显示反射类型对象的名称和种类 fmt.Printf("name:'%v' kind:'%v'\n", typeOfCat.Name(), typeOfCat.Kind()) // 取类型的元素 typeOfCat = typeOfCat.Elem() // 显示反射类型对象的名称和种类 fmt.Printf("element name: '%v', element kind: '%v'\n", typeOfCat.Name(), typeOfCat.Kind()) }
运行结果如下:
代码说明如下:
第 13 行,创建了 cat 结构体的实例,ins 是一个 *cat 类型的指针变量。
第 15 行,对指针变量获取反射类型信息。
第 17 行,输出指针变量的类型名称和种类。Go语言的反射中对所有指针变量的种类都是 Ptr,但需要注意的是,指针变量的类型名称是空,不是 *cat。
第 19 行,取指针类型的元素类型,也就是 cat 类型。这个操作不可逆,不可以通过一个非指针类型获取它的指针类型。
第 21 行,输出指针变量指向元素的类型名称和种类,得到了 cat 的类型名称(cat)和种类(struct)。
【相关推荐:Go视频教程】
The above is the detailed content of Does go language have reflection?. For more information, please follow other related articles on the PHP Chinese website!