Les bases de l'imbrication de structs
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy — leçon 35 sur 107.
L'imbrication de structures (struct embedding) est le mécanisme de Go permettant d'inclure un type struct à l'intérieur d'un autre. Au lieu d'utiliser un nom de champ, vous spécifiez simplement le type, et Go promeut les champs de la struct imbriquée vers la struct externe.
Voici la syntaxe de base :
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // incorporé - pas de nom de champ
}
Lorsque vous imbriquez Address dans Person, vous pouvez accéder aux champs imbriqués directement sur la structure externe :
func main() {
p := Person{
Name: "Alice",
Address: Address{
City: "London",
Country: "UK",
},
}
fmt.Println(p.City) // London - accès direct
fmt.Println(p.Country) // UK - accès direct
fmt.Println(p.Address.City) // fonctionne également
}
Remarquez comment p.City fonctionne sans écrire explicitement p.Address.City. Go promeut automatiquement les champs de la structure imbriquée, les rendant accessibles comme s'ils appartenaient à la structure externe. Vous pouvez toujours y accéder via le nom du type imbriqué si nécessaire.
Cela diffère des structures imbriquées classiques où vous devez toujours utiliser le nom du champ pour accéder aux champs internes. L'imbrication (embedding) crée une API plus plate et plus pratique tout en conservant le regroupement logique des données associées.
Défi
FacileConstruisons un système d'immatriculation de véhicules qui utilise l'imbrication de structures (struct embedding) pour créer un modèle de données propre et organisé. Vous séparerez les informations de contact des détails du véhicule tout en permettant un accès direct à tous les champs grâce à l'imbrication.
Vous organiserez votre code sur deux fichiers :
vehicle.go: Créez deux structures qui fonctionnent ensemble par imbrication :- Une structure
ContactInfoavec les champsOwnerNameetPhone(tous deux des chaînes de caractères) - Une structure
Vehiclequi imbriqueContactInfo(sans nom de champ) et ajoute ses propres champsMake,Model, etYear
SummarysurVehiclequi retourne une chaîne formatée contenant toutes les informations sur le véhicule et le contact.- Une structure
main.go: Lisez les détails du véhicule et du propriétaire à partir de l'entrée, créez une instance deVehicleavecContactInfoimbriqué, et démontrez l'accès aux champs imbriqués à la fois directement et via le nom du type imbriqué. Affichez le résumé du véhicule à la fin.
Les entrées suivantes seront fournies :
- Ligne 1 : Nom du propriétaire
- Ligne 2 : Numéro de téléphone
- Ligne 3 : Marque du véhicule
- Ligne 4 : Modèle du véhicule
- Ligne 5 : Année (entier)
Votre méthode Summary doit retourner une chaîne dans ce format :
[Year] [Make] [Model] - Owner: [OwnerName], Phone: [Phone]Dans votre fichier principal, démontrez la promotion de champ (field promotion) en affichant :
- Le nom du propriétaire accédé directement sur le Vehicle (par exemple,
v.OwnerName) - Le téléphone accédé via le type imbriqué (par exemple,
v.ContactInfo.Phone) - Le résumé complet provenant de votre méthode
Summary
Par exemple, avec Alice Smith, 555-1234, Toyota, Camry, et 2023, votre sortie devrait être :
Alice Smith
555-1234
2023 Toyota Camry - Owner: Alice Smith, Phone: 555-1234Remarquez comment les deux modes d'accès fonctionnent — l'accès direct via la promotion de champ et l'accès explicite via le nom du type imbriqué — vous offrant ainsi une flexibilité dans la manipulation des données imbriquées.
Aide-mémoire
L'imbrication de structures (struct embedding) vous permet d'inclure un type de structure à l'intérieur d'un autre sans spécifier de nom de champ. Les champs de la structure imbriquée sont promus à la structure externe, ce qui les rend directement accessibles.
Syntaxe de base
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // embedded - no field name
}
Accès aux champs imbriqués
Vous pouvez accéder aux champs imbriqués de deux manières :
p := Person{
Name: "Alice",
Address: Address{
City: "London",
Country: "UK",
},
}
// Direct access (field promotion)
fmt.Println(p.City) // London
// Through embedded type name
fmt.Println(p.Address.City) // London
Go promeut automatiquement les champs de la structure imbriquée, permettant un accès direct comme s'ils appartenaient à la structure externe. Vous pouvez toujours y accéder via le nom du type imbriqué si nécessaire.
Essayez vous-même
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Lire le nom du propriétaire
ownerName, _ := reader.ReadString('\n')
ownerName = strings.TrimSpace(ownerName)
// Lire le numéro de téléphone
phone, _ := reader.ReadString('\n')
phone = strings.TrimSpace(phone)
// Lire la marque du véhicule
make, _ := reader.ReadString('\n')
make = strings.TrimSpace(make)
// Lire le modèle du véhicule
model, _ := reader.ReadString('\n')
model = strings.TrimSpace(model)
// Lire l'année
yearStr, _ := reader.ReadString('\n')
yearStr = strings.TrimSpace(yearStr)
year, _ := strconv.Atoi(yearStr)
// TODO: Créer une instance de Vehicle avec ContactInfo incorporé
// Utiliser les valeurs lues à partir de l'entrée ci-dessus
// TODO: Afficher le nom du propriétaire accédé directement sur le Vehicle (promotion de champ)
// Exemple: fmt.Println(v.OwnerName)
// TODO: Afficher le téléphone accédé via le nom du type incorporé
// Exemple: fmt.Println(v.ContactInfo.Phone)
// TODO: Afficher le résumé complet en utilisant la méthode Summary
// Exemple: fmt.Println(v.Summary())
// Supprimer ces lignes une fois la solution implémentée
_ = ownerName
_ = phone
_ = make
_ = model
_ = year
}
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 vs non exportésIntroduction à la POO en GoLes Structs comme ClassesDéfinir des méthodes sur les StructsReceveurs par pointeur vs par valeurInitialisation de StructsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL'interface comme contratInterface vide (any)Assertion de typeType SwitchComposition d'interfacesInterfaces Stringer & ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter & SetterMasquage d'informations en GoRécapitulatif - Dossiers étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesContournement pour les méthodes génériquesRécapitulatif - Collections génériques13Patrons de conception, Partie 1
Introduction aux Design PatternsPatron SingletonPatron FactoryPatron Abstract FactoryPatron ObserverPatron Strategy2Exploration approfondie des Types et Structs
Types de base et compositesDéfinitions de types personnalisésTags de StructStructs anonymesStructs imbriquéesValeurs par défaut et Zero ValuesRécapitulatif - Carnet de contacts5Composition plutôt qu'héritage
Pourquoi Go n'a pas d'héritageLes bases de l'imbrication de structsPromotion de méthodesImbriquer plusieurs structsImbrication vs AgrégationMasquage de méthodes imbriquéesRécapitulatif - Hiérarchie des employés8Gestion des erreurs & POO
L'interface errorTypes d'erreurs personnalisésError Wrapping (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - File Parser11Bibliothèque standard et POO
io.Reader & io.WriterL'interface sort.InterfaceL'interface fmt.Stringerencoding/json avec les StructsL'interface http.HandlerRécapitulatif - Modèles d'API REST14Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositeMiddleware en tant que Décorateur3Pointeurs et Mémoire
Bases des pointeurs en GoPointeurs vers des structsPassage par valeur vs référenceLa fonction new()Garbage Collection en GoRécapitulatif - Constructeur de liste chaînée6Le polymorphisme en Go
Le polymorphisme via les interfacesLe Duck Typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif - Processeur de paiement9Concurrence et POO
Bases des GoroutinesChannels et CommunicationChannels avec buffer vs sans bufferL'instruction Selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures Thread-SafeRécapitulatif - Worker Pool