Définir des structures dans Go

introduction

Construire des abstractions autour de détails concrets est le meilleur outil qu'un langage de programmation peut offrir à un développeur. Les structures permettent aux développeurs de Go de décrire le monde dans lequel un programme Go fonctionne. Au lieu de raisonner sur des chaînes décrivant unStreet,City ou unPostalCode, les structs nous permettent plutôt de parler d'unAddress. Ils servent de lien naturel pourdocumentation dans nos efforts pour dire aux futurs développeurs (nous y compris) quelles données sont importantes pour nos programmes Go et comment le futur code devrait utiliser ces données de manière appropriée. Les structures peuvent être définies et utilisées de différentes manières. Dans ce tutoriel, nous allons examiner chacune de ces techniques.

Définir des structures

Les structures fonctionnent comme des formulaires papier que vous pourriez utiliser, par exemple, pour déclarer vos impôts. Les formulaires papier peuvent comporter des champs pour des éléments d’information textuels, tels que vos noms de famille. Outre les champs de texte, les formulaires peuvent avoir des cases à cocher pour indiquer des valeurs booléennes telles que «marié» ou «célibataire» ou des champs de date pour la date de naissance. De la même manière, les structures collectent différentes données et les organisent sous différents noms de champs. Lorsque vous initialisez une variable avec une nouvelle structure, c’est comme si vous avez photocopié un formulaire et que vous l’avez préparé à remplir.

Pour créer une nouvelle structure, vous devez d’abord donner à Go un plan détaillé qui décrit les champs qu’elle contient. Cette définition de structure commence généralement par le mot-clétype suivi du nom de la structure. Après cela, utilisez le mot-cléstruct suivi d'une paire d'accolades{} où vous déclarez les champs que la structure contiendra. Une fois que vous avez défini la structure, vous pouvez ensuite déclarer les variables qui utilisent cette définition de structure. Cet exemple définit une structure et l'utilise:

package main

import "fmt"

type Creature struct {
    Name string
}

func main() {
    c := Creature{
        Name: "Sammy the Shark",
    }
    fmt.Println(c.Name)
}

Lorsque vous exécutez ce code, vous verrez cette sortie:

outputSammy the Shark

Nous définissons d'abord une structureCreature dans cet exemple, contenant un champName de typestring. Dans le corps demain, nous créons une instance deCreature en plaçant une paire d'accolades après le nom du type,Creature, puis en spécifiant les valeurs des champs de cette instance. L'instance dec aura son champName défini sur «Sammy the Shark». Dans l’invocation de la fonctionfmt.Println, nous récupérons les valeurs du champ de l’instance en plaçant un point après la variable dans laquelle l’instance a été créée, suivi du nom du champ auquel nous souhaitons accéder. Par exemple,c.Name dans ce cas renvoie le champName.

Lorsque vous déclarez une nouvelle instance d'une structure, vous énumérez généralement les noms de champs avec leurs valeurs, comme dans le dernier exemple. Sinon, si chaque valeur de champ doit être fournie lors de l'instanciation d'une structure, vous pouvez omettre les noms de champs, comme dans cet exemple:

package main

import "fmt"

type Creature struct {
    Name string
    Type string
}

func main() {
    c := Creature{"Sammy", "Shark"}
    fmt.Println(c.Name, "the", c.Type)
}

La sortie est la même que celle du dernier exemple:

outputSammy the Shark

Nous avons ajouté un champ supplémentaire àCreature pour suivre lesType de créature en tant questring. Lors de l'instanciation deCreature dans le corps demain, nous avons choisi d'utiliser le formulaire d'instanciation plus court en fournissant des valeurs pour chaque champ dans l'ordre et en omettant leurs noms de champ. Dans la déclarationCreature{"Sammy", "Shark"}, le champName prend la valeurSammy et le champType prend la valeurShark carName apparaît en premier dans le déclaration de type, suivie deType.

Ce formulaire de déclaration abrégé présente quelques inconvénients qui ont amené la communauté Go à préférer le formulaire plus long dans la plupart des cas. Vous devez fournir des valeurs pour chaque champ de la structure lorsque vous utilisez la déclaration courte - vous ne pouvez pas ignorer les champs qui ne vous intéressent pas. Cela provoque rapidement des déclarations courtes pour les structures avec de nombreux champs de créer de la confusion. Pour cette raison, la déclaration de structures à l'aide de la forme courte est généralement utilisée avec des structures comportant peu de champs.

Les noms de champs dans les exemples jusqu’à présent ont tous commencé par des lettres majuscules. Ceci est plus important qu'une préférence stylistique. L'utilisation de lettres majuscules ou minuscules pour les noms de champs détermine si vos noms de champs seront accessibles au code exécuté dans d'autres packages.

Exportation de champs

Les champs d'une structure suivent les mêmes règles d'exportation que les autres identificateurs du langage de programmation Go. Si un nom de champ commence par une lettre majuscule, il sera lisible et inscriptible par un code situé en dehors du paquet où la structure a été définie. Si le champ commence par une lettre minuscule, seul le code du paquet de cette structure sera capable de lire et d’écrire ce champ. Cet exemple définit les champs exportés et ceux qui ne le sont pas:

package main

import "fmt"

type Creature struct {
    Name string
    Type string

    password string
}

func main() {
    c := Creature{
        Name: "Sammy",
        Type: "Shark",

        password: "secret",
    }
    fmt.Println(c.Name, "the", c.Type)
    fmt.Println("Password is", c.password)
}

Cela produira:

outputSammy the Shark
Password is secret

Nous avons ajouté un champ supplémentaire à nos exemples précédents,secret. secret est un champstring non exporté, ce qui signifie que tout autre package qui tente d'instancier unCreature ne pourra pas accéder ou définir son champsecret. Dans le même package, nous pouvons accéder à ces champs, comme le montre cet exemple. Étant donné quemain est également dans le packagemain, il est capable de référencerc.password et de récupérer la valeur qui y est stockée. Il est courant d’avoir des champs non exportés dans les structures avec un accès via des méthodes exportées.

Structures en ligne

En plus de définir un nouveau type pour représenter une structure, vous pouvez également définir une structure en ligne. Ces définitions de structure à la volée sont utiles dans les situations où inventer de nouveaux noms pour des types de structure serait un effort inutile. Par exemple, les tests utilisent souvent une structure pour définir tous les paramètres qui constituent un cas de test particulier. Il serait fastidieux de trouver de nouveaux noms commeCreatureNamePrintingTestCase lorsque cette structure est utilisée à un seul endroit.

Les définitions de structure en ligne apparaissent à droite d'une affectation de variable. Vous devez en fournir une instanciation immédiatement après en fournissant une paire d'accolades supplémentaire avec des valeurs pour chacun des champs que vous définissez. L'exemple suivant montre une définition de structure inline:

package main

import "fmt"

func main() {
    c := struct {
        Name string
        Type string
    }{
        Name: "Sammy",
        Type: "Shark",
    }
    fmt.Println(c.Name, "the", c.Type)
}

La sortie de cet exemple sera:

outputSammy the Shark

Plutôt que de définir un nouveau type décrivant notre structure avec le mot clétype, cet exemple définit une structure en ligne en plaçant la définition destruct immédiatement après l'opérateur d'affectation courte,:=. Nous définissons les champs de la structure comme dans les exemples précédents, mais nous devons alors immédiatement fournir une autre paire d'accolades et les valeurs que chaque champ prendra. L'utilisation de cette structure est maintenant exactement la même qu'auparavant - nous pouvons nous référer aux noms de champs en utilisant la notation par points. L'endroit le plus courant pour afficher les structures en ligne déclarées est lors des tests, car des structures uniques sont souvent définies pour contenir des données et des attentes pour un scénario de test particulier.

Conclusion

Les structures sont des collections de données hétérogènes définies par les programmeurs pour organiser les informations. La plupart des programmes traitent d'énormes volumes de données, et sans structures, il deviendrait difficile de se rappeler quelles variablesstring ouint appartenaient ensemble ou lesquelles étaient différentes. La prochaine fois que vous vous retrouverez à jongler avec des groupes de variables, demandez-vous si ces variables seraient peut-être mieux regroupées en utilisant unstruct. Ces variables ont peut-être toujours décrit un concept de niveau supérieur.