Introduction aux tags de struct
Le système de tags dans les structures Go est un mécanisme de métadonnées qui permet d'annoter les champs d'une struct. Dans le contexte du binding Qt pour Go (qt), ces tags sont utilisés pour reproduire certaines fnoctionnalités du système Meta-Object Compiler (moc) de Qt, notamment pour la déclaration des signaux, des slots et d'autres éléments de métaprogrammation.
Un tag se présente sous la forme d'une chaîne littérale entre accents graves, située après le type d'un champ. Sa syntaxe générale est clef:"valeur". Par exemple, pour la sérialisation JSON :
type CompteUtilisateur struct {
Identifiant int `json:"id_utilisateur"`
Nom string `json:"nom_complet"`
}
Le package reflect de Go permet d'accéder à ces annotations à l'exécution :
c := &CompteUtilisateur{Identifiant: 42, Nom: "Alice"}
t := reflect.TypeOf(c).Elem()
champ, _ := t.FieldByName("Nom")
fmt.Println(champ.Tag.Get("json")) // Affiche : nom_complet
Les tags -> et <- pour la connexion signal-slot
Dans qt, les tags -> (envoi) et <- (réception) sont utilisés en combinaison avec les tags signal et slot pour établir des connexions entre objets, évitant ainsi d'écrire explicitement des appels à Connect.
Voici un exemple de slot qui réagit à un signal externe :
type Graphique struct {
core.QObject
*charts.QChart
_ func() `constructor:"initialiser"`
// Le slot 'rafraichir' est connecté au signal 'timeout' du minuteur membre.
_ func() `slot:"rafraichir,<-(this.minuteur.timeout)"`
}
La déclaratoin ci-dessus est équivalente au code Go suivant :
this.minuteur.ConnectTimeout(this.rafraichir)
Il est possible d'omettre le nom du signal si celui-ci correspond au nom de la fonction cible. Ainsi, slot:"rafraichir,<-(this.minuteur)" connectera automatiquement le slot rafraichir au signal Timeout de this.minuteur.
À l'inverce, le tag -> permet d'émettre un signal vers un récepteur externe :
type Dialogue struct {
core.QObject
_ func() `constructor:"creer"`
// Le signal 'masquer' est connecté à une fonction du contrôleur.
_ func() `signal:"masquer,->(controleur.Gestionnaire)"`
}
Cela correspond à :
this.ConnectMasquer(controleur.Gestionnaire.masquer)
Règles d'utilisation et bonnes pratiques
- Portée des objets : Le chemin spécifié dans les parenthèses peut désigner un objet global (par exemple,
monpackage.MonObjet), l'instance courante (this), ou un champ de l'instance (this.MonChamp). - Héritage : Pour connecter des signaux ou slots hérités d'une classe de base Qt, il faut utiliser une syntaxe explicite comme
this.ClasseDeBase.Methode. - Contexte d'utilisation : Les tags
->et<-sont particulièrement adaptés pour les interactions entre objets distincts ou pour l'intégration avec QML. Pour les connexions internes à une même instance, le tagauto(utilisé seul) peut être plus simple et lisible.
Comparaison entre auto, -> et <-
Ces trois mécanismes automatiques ont des cas d'application distincts :
| Tag | Usage recommandé |
|---|---|
signal:"nom,auto" |
Pour connecter automatiquement un signal à un slot de la même instance. À privilégier pour la connexion interne. |
-> ou <- |
Pour interconnecter des objets différents ou réutiliser des signaux/slots de membres ou de classes de base. |
L'objectif commun est de réduire le code boilerplate lié aux appels Connect, tout en centralisant la logique de connexion au sein de la déclaration de la structure.