Bases de la réflexion
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 83 sur 107.
La réflexion permet à un programme d’examiner et de manipuler sa propre structure lors de l’exécution. Le package reflect de Go offre cette fonctionnalité, ce qui vous permet d’inspecter les types, de lire les champs des structures et d’appeler des méthodes dynamiquement.
Les deux types fondamentaux de la réflexion sont reflect.Type et reflect.Value. Vous les obtenez à l’aide de reflect.TypeOf() et reflect.ValueOf() :
import "reflect"
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
fmt.Println(t.Name()) // Person
fmt.Println(t.Kind()) // struct
fmt.Println(v.NumField()) // 2Vous pouvez parcourir les champs d’une structure pour examiner leurs noms, types et valeurs :
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
// Sortie :
// Name: Alice
// Age: 30La réflexion est puissante, mais elle comporte des compromis : elle contourne la vérification des types à la compilation, s’exécute plus lentement qu’un accès direct et rend le code plus difficile à comprendre. Utilise-la avec parcimonie pour des tâches comme le marshaling JSON, le mapping ORM ou la création d’utilitaires génériques lorsque le type n’est pas connu à la compilation.
Défi
FacileConstruisons un inspecteur de structures qui utilise la réflexion pour examiner n’importe quelle structure et en rendre compte ! Il s’agit d’un cas d’utilisation pratique de la réflexion : créer des utilitaires qui fonctionnent avec des types inconnus au moment de la compilation.
Vous organiserez votre code sur deux fichiers :
inspector.go: créez votre utilitaire d’inspection fondé sur la réflexion.Construisez une fonction
InspectStruct(v any) stringqui utilise le packagereflectpour examiner toute structure qui lui est transmise. Votre fonction doit renvoyer un rapport mis en forme contenant :- Le nom du type de la structure
- Le genre de la structure (doit être « struct »)
- Le nombre de champs
- Pour chaque champ : le nom du champ, son type et sa valeur actuelle
Le format de sortie doit être :
Type: [TypeName] Kind: struct Fields: [count] - [FieldName] ([FieldType]): [Value] - [FieldName] ([FieldType]): [Value] ...Utilisez
reflect.TypeOf()pour obtenir les informations de type etreflect.ValueOf()pour accéder aux valeurs des champs. Parcourez les champs en utilisantNumField()etField(i)sur le type pour les métadonnées, ainsi queField(i)sur la valeur pour les valeurs réelles.main.go: définissez des structures d’exemple et utilisez votre inspecteur.Lisez un type de structure (
productouemployee) et les valeurs de ses champs, puis créez la structure appropriée et inspectez-la.Pour
product: créez une structureProductavec les champsName(string),Price(float64) etInStock(bool). Lisez le nom, le prix et le statut des stocks.Pour
employee: créez une structureEmployeeavec les champsID(int),Name(string) etDepartment(string). Lisez l’ID, le nom et le service.Transmettez la structure créée à
InspectStructet affichez le résultat.
Les entrées suivantes seront fournies :
- Ligne 1 : type de structure (
productouemployee) - Lignes suivantes : valeurs des champs de ce type de structure
Par exemple, avec :
product
Laptop
999.99
trueVotre sortie doit être :
Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): trueEt avec :
employee
42
Alice Johnson
EngineeringVotre sortie doit être :
Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): EngineeringEt avec :
product
Headphones
79.50
falseVotre sortie doit être :
Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): falseRemarquez comment votre inspecteur fonctionne avec différents types de structures sans connaître leur structure à l’avance. C’est toute la puissance de la réflexion ! La même fonction InspectStruct gère dynamiquement les structures Product et Employee.
Essayez vous-même
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Structure Product avec les champs Name, Price et InStock
type Product struct {
Name string
Price float64
InStock bool
}
// Structure Employee avec les champs ID, Name et Department
type Employee struct {
ID int
Name string
Department string
}
func main() {
reader := bufio.NewReader(os.Stdin)
// Lire le type de structure
structType, _ := reader.ReadString('\n')
structType = strings.TrimSpace(structType)
if structType == "product" {
// Lire les champs du produit
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
inStockStr, _ := reader.ReadString('\n')
inStockStr = strings.TrimSpace(inStockStr)
inStock, _ := strconv.ParseBool(inStockStr)
// TODO: Créer une structure Product avec les valeurs lues
// TODO: Appeler InspectStruct avec le produit et afficher le résultat
} else if structType == "employee" {
// Lire les champs de l'employé
idStr, _ := reader.ReadString('\n')
idStr = strings.TrimSpace(idStr)
id, _ := strconv.Atoi(idStr)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
department, _ := reader.ReadString('\n')
department = strings.TrimSpace(department)
// TODO: Créer une structure Employee avec les valeurs lues
// TODO: Appeler InspectStruct avec l'employé et afficher le résultat
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO en Go
Fichiers externesEspace de travail et modules GoPackages et importsNoms exportés et non exportésIntroduction à la POO en GoStructs comme classesDéfinir des méthodes sur des structsRécepteurs pointeurs ou par valeurInitialisation des structsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL’interface comme contratInterface vide (any)Assertion de typeCommutation de typeComposition d’interfacesInterfaces Stringer et ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter et SetterDissimulation de l’information en GoRécapitulatif – Fiches d’étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesSolution de contournement pour les méthodes génériquesRécapitulatif - Collection générique2Plongée approfondie dans les types et les structs
Types de base et compositesDéfinitions de types personnalisésTags de structStructs anonymesStructs imbriquésValeurs zéro et valeurs par défautRécapitulatif - Carnet de contacts5La composition plutôt que l’héritage
Pourquoi Go n’a pas d’héritageBases de l’inclusion de structsPromotion des méthodesInclure plusieurs structsInclusion ou agrégationMasquage des méthodes inclusesRécapitulatif : hiérarchie des employés8Gestion des erreurs et POO
L’interface errorTypes d’erreurs personnalisésEnrobage des erreurs (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - Analyseur de fichiers11Bibliothèque standard et POO
io.Reader et io.Writersort.InterfaceInterface fmt.Stringerencoding/json avec des structsInterface http.HandlerRécapitulatif - Modèles d’API REST14Modèles de conception – Partie 2
Modèle CommandeModèle AdaptateurModèle DécorateurModèle Méthode modèleModèle ÉtatModèle CompositeMiddleware comme décorateur3Pointeurs et mémoire
Notions de base des pointeurs en GoPointeurs vers des structuresPassage par valeur ou par référenceLa fonction new()Garbage collection en GoRécapitulatif - Constructeur de listes chaînées6Polymorphisme en Go
Polymorphisme via les interfacesDuck typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif – Processeur de paiements9Concurrence et POO
Bases des GoroutinesCanaux et communicationCanaux tamponnés ou non tamponnésInstruction selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures thread-safeRécapitulatif - Pool de workers12Concepts avancés de la POO
Pattern des options fonctionnellesPattern Builder en GoChaînage de méthodesAlias de types vs définitionsBases de la réflexionVue d’ensemble de la génération de codeEntraînez-vous par vous-même : Compilateur Go en ligne