Maison  >  Article  >  développement back-end  >  Le langage go a-t-il une réflexion ?

Le langage go a-t-il une réflexion ?

青灯夜游
青灯夜游original
2022-11-25 16:56:143501parcourir

go langage a réflexion. Le langage Go fournit un mécanisme pour mettre à jour et vérifier la valeur des variables, les méthodes d'appel des variables et les opérations intrinsèques prises en charge par les variables au moment de l'exécution, mais les types spécifiques de ces variables ne sont pas connus au moment de la compilation. La réflexion dans le langage Go est prise en charge par le package Reflection, qui définit deux types importants : Type et Valeur. Toute valeur d'interface dans la réflexion peut être comprise comme composée de deux parties : Reflect.Type et Reflect.Value.

Le langage go a-t-il une réflexion ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.

Le langage Go fournit un mécanisme pour mettre à jour et vérifier la valeur des variables, appeler des méthodes de variables et des opérations intrinsèques prises en charge par les variables au moment de l'exécution, mais les types spécifiques de ces variables ne sont pas connus au moment de la compilation. La réflexion nous permet également de traiter le type lui-même comme un type valeur de première classe.

Réflexion dans le langage Go

La réflexion fait référence à la possibilité d'accéder et de modifier le programme lui-même pendant l'exécution du programme. Lorsque le programme est compilé, les variables sont converties en adresses mémoire et en noms de variables. ne sera pas écrit par le compilateur. Dans la partie exécutable, le programme ne peut pas obtenir ses propres informations lors de l'exécution du programme.

Les langages prenant en charge la réflexion peuvent intégrer les informations de réflexion des variables, telles que les noms de champs, les informations de type, les informations de structure, etc., dans le fichier exécutable lors de la compilation du programme, et fournir au programme une interface pour accéder aux informations de réflexion. , afin que le programme puisse s'exécuter. Fournit un accès aux informations de réflexion de type et la possibilité de les modifier.

Le langage C/C++ ne prend pas en charge la fonction de réflexion et ne peut fournir que des informations de type d'exécution de programme très affaiblies via typeid ; les langages tels que Java et C# prennent tous en charge des fonctions de réflexion dynamiques telles que Lua et JavaScript ; , en raison de leurs propres caractéristiques grammaticales. Cela permet au code d'accéder à la propre valeur et aux informations de type du programme au moment de l'exécution, aucun système de réflexion n'est donc nécessaire.

Le système de réflexion du programme en langage Go ne peut pas obtenir tous les types d'informations dans un espace fichier exécutable ou un package. Il doit utiliser le lexical, l'analyseur de syntaxe et l'arbre de syntaxe abstraite (AST) correspondants dans la bibliothèque standard pour effectuer le traitement du code source. . Scannez pour obtenir ces informations.

Le langage Go fournit le package de réflexion pour accéder aux informations de réflexion du programme.

reflect package

La réflexion dans le langage Go est prise en charge par le package Reflect, qui définit deux types importants, Type et Valeur. Toute valeur d'interface dans la réflexion peut être comprise comme réfléchie.Type et réflexion.La valeur se compose de. deux parties, et le package Reflect fournit deux fonctions, Reflect.TypeOf et Reflect.ValueOf, pour obtenir la valeur et le type de n'importe quel objet.

Objet de type réfléchi (reflect.Type)

Dans un programme en langage Go, vous pouvez utiliser la fonction Reflect.TypeOf() pour obtenir un objet de type (reflect.Type) avec n'importe quelle valeur à laquelle le programme peut accéder. n'importe quel objet de type via l'objet de type.Les informations de type de la valeur sont les suivantes :

package main
import (
    "fmt"
    "reflect"
)
func main() {
    var a int
    typeOfA := reflect.TypeOf(a)
    fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

Les résultats d'exécution sont les suivants :

Le langage go a-t-il une réflexion ?

La description du code est la suivante. suit :

  • La ligne 9 définit une variable de type int.

  • À la ligne 10, l'objet type typeOfA de la variable a est obtenu via réfléchissant.TypeOf(), et le type est réflexion.Type().

  • À la ligne 11, via la fonction membre de l'objet de type typeOfA, le nom de type de la variable typeOfA peut être obtenu respectivement int, et le type (Kind) est int.

Type et genre de réflexion

Lorsque vous utilisez la réflexion, vous devez d'abord comprendre la différence entre le type et le genre. En programmation, le type le plus couramment utilisé est le type, mais en réflexion, lorsqu'il faut distinguer une grande variété de types, le type (Kind) est utilisé. Par exemple, lorsque vous devez juger uniformément les pointeurs dans les types, il est plus pratique d'utiliser des informations kind (Kind).

1) Définition du type de réflexion (Kind)

Type (Type) dans le programme en langage Go fait référence aux types de données natifs du système, tels que int, string, bool, float32 et autres types, ainsi que ceux définis à l'aide le mot-clé type Types dont les noms sont les noms des types eux-mêmes. Par exemple, lorsque vous utilisez le type A struct{} pour définir une structure, A est le type de struct{}.

Kind fait référence au type d'objet, qui est défini comme suit dans le package Reflect :

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 et Chan sont des types de référence, qui sont similaires aux pointeurs utilisés, mais sont toujours indépendants dans la définition de la constante de type. Catégorie, n'appartient pas à Ptr. La structure définie par le type A struct{} appartient au type Struct et *A appartient à Ptr.

2) Récupérer le nom et le type du type à partir de l'objet type

La méthode d'acquisition de réflexion correspondant au nom du type dans le langage Go est la méthode Name() dans Reflect.Type, qui renvoie une chaîne représentant le nom du type ; le type appartient à Kind (Kind) utilise la méthode Kind() dans Reflect.Type et renvoie une constante de type Reflect.Kind.

下面的代码中会对常量和结构体进行类型信息获取。

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())
}

运行结果如下:

Le langage go a-t-il une réflexion ?

代码说明如下:

  • 第 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())
}

运行结果如下:

Le langage go a-t-il une réflexion ?

代码说明如下:

  • 第 13 行,创建了 cat 结构体的实例,ins 是一个 *cat 类型的指针变量。

  • 第 15 行,对指针变量获取反射类型信息。

  • 第 17 行,输出指针变量的类型名称和种类。Go语言的反射中对所有指针变量的种类都是 Ptr,但需要注意的是,指针变量的类型名称是空,不是 *cat。

  • 第 19 行,取指针类型的元素类型,也就是 cat 类型。这个操作不可逆,不可以通过一个非指针类型获取它的指针类型。

  • 第 21 行,输出指针变量指向元素的类型名称和种类,得到了 cat 的类型名称(cat)和种类(struct)。

【相关推荐:Go视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn