Exercice - Utiliser des mappages

Effectué

Dans le langage Go, un mappage est une table de hachage qui constitue une collection de paires clé/valeur. Toutes les clés d’un mappage doivent être du même type; tout comme les valeurs. Toutefois, vous pouvez utiliser des types différents pour les clés et les valeurs. Par exemple, les clés peuvent être des nombres, et les valeurs peuvent être des chaînes. Pour accéder à un élément en particulier d’un mappage, vous devez référencer sa clé.

Déclarer et initialiser un mappage

Pour déclarer un mappage, vous devez utiliser le mot clé map. Vous définissez ensuite la clé et le type de valeur de la façon suivante : map[T]T. Par exemple, si vous souhaitez créer un mappage contenant l’âge des étudiants, vous pouvez utiliser le code suivant :

package main

import "fmt"

func main() {
    studentsAge := map[string]int{
        "john": 32,
        "bob":  31,
    }
    fmt.Println(studentsAge)
}

Quand vous exécutez le code précédent, vous obtenez la sortie suivante :

map[bob:31 john:32]

Si vous ne souhaitez pas initialiser un mappage avec des éléments, vous pouvez utiliser la fonction make() intégrée pour créer le mappage dans la section précédente. Vous pouvez utiliser le code suivant pour créer un mappage vide :

studentsAge := make(map[string]int)

Les mappages sont dynamiques. Une fois que vous avez créé des éléments, vous pouvez y accéder, les ajouter ou les supprimer. Nous allons explorer ces opérations.

Ajouter des éléments

Pour ajouter des éléments, vous n’avez pas besoin d’utiliser une fonction intégrée comme vous le feriez pour des coupes. Les mappages sont plus simples à utiliser. Il vous suffit de définir une clé et une valeur. Si la paire n’existe pas, l’élément est ajouté au mappage.

Nous allons réécrire le code que nous avons utilisé précédemment pour créer une carte à l’aide de la fonction make. Ensuite, nous ajouterons des éléments au mappage. Vous pouvez utiliser le code suivant :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Quand vous exécutez le code, vous obtenez la même sortie que précédemment :

map[bob:31 john:32]

Notez que nous avons ajouté des éléments à un mappage qui a été initialisé. Toutefois, si vous essayez d’effectuer la même opération avec un mappage nil, vous obtiendrez une erreur. Par exemple, le code suivant ne fonctionnera pas :

package main

import "fmt"

func main() {
    var studentsAge map[string]int
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Quand vous exécutez le code précédent, vous obtenez l’erreur suivante :

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
        /Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2

Pour éviter tout problème lorsque vous ajoutez des éléments à un mappage, vous devez créer un mappage vide (pas un mappage nil) à l’aide de la fonction make, comme nous l’avons montré dans l’extrait de code précédent. Cette règle s’applique uniquement lorsque vous ajoutez des éléments. Si vous exécutez des recherches, des suppressions ou des opérations de boucle dans un mappage nil, Go ne générera pas d’erreur. Nous allons voir ce comportement dans un moment.

Accéder aux éléments

Pour accéder aux éléments d’un mappage, vous devez utiliser la notation d’indice habituelle m[key], comme vous le feriez pour des tableaux ou des coupes. Voici un exemple simple d’accès à un élément :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Bob's age is", studentsAge["bob"])
}

Lorsque vous utilisez la notation d’indice dans un mappage, vous recevez toujours une réponse, même si la clé ne se trouve pas dans le mappage. Go ne génère pas d’erreur quand vous accédez à un élément qui n’existe pas. Au lieu de cela, il vous retourne la valeur par défaut. Vous pouvez vérifier ce comportement à l’aide du code suivant :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Christy's age is", studentsAge["christy"])
}

Quand vous exécutez le code précédent, vous obtenez la sortie suivante :

Christy's age is 0

Dans de nombreux cas, Go ne retourne pas d’erreur quand vous accédez à un élément qui ne se trouve pas dans un mappage. Toutefois, il peut arriver que vous ayez besoin de savoir si un élément existe ou non. Dans le langage Go, la notation d’indice d’un mappage peut générer deux valeurs. La première est la valeur d’un élément. La deuxième est un indicateur booléen qui indique si la clé existe ou non.

Pour résoudre le problème du dernier extrait de code, vous pouvez utiliser le code suivant :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    age, exist := studentsAge["christy"]
    if exist {
        fmt.Println("Christy's age is", age)
    } else {
        fmt.Println("Christy's age couldn't be found")
    }
}

Quand vous exécutez le code précédent, vous obtenez la sortie suivante :

Christy's age couldn't be found

Utilisez le deuxième extrait de code pour vérifier si une clé se trouve bien dans un mappage avant d’accéder à celle-ci.

Supprimer des éléments

Pour supprimer un élément d’un mappage, utilisez la fonction intégrée delete(). Voici un exemple montrant comment supprimer des éléments d’un mappage :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "john")
    fmt.Println(studentsAge)
}

Quand vous exécutez le code, vous obtenez la sortie suivante :

map[bob:31]

Comme nous l’avons déjà dit, si vous tentez de supprimer un élément qui n’existe pas, Go ne générera pas d’erreur. Voici un exemple de ce comportement :

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "christy")
    fmt.Println(studentsAge)
}

Quand vous exécutez le code, vous n’obtenez pas d’erreur et vous voyez la sortie suivante :

map[bob:31 john:32]

Exécuter une boucle dans un mappage

Maintenant, voyons comment exécuter une boucle dans un mappage pour accéder à tous ses éléments par programmation. Pour cela, vous pouvez utiliser la boucle basée sur une plage, comme dans l’exemple suivant :

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    for name, age := range studentsAge {
        fmt.Printf("%s\t%d\n", name, age)
    }
}

Quand vous exécutez le code précédent, vous obtenez la sortie suivante :

john    32
bob     31

Remarquez que vous pouvez stocker les informations de clé et les informations de valeur dans des variables différentes. Ici, nous plaçons la clé dans la variable name et la valeur dans la variable age. Par conséquent, range produit d’abord la clé d’un élément, et ensuite la valeur de cet élément. Vous pouvez ignorer l’un des deux à l’aide de la variable _, comme dans l’exemple suivant :

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for _, age := range studentsAge {
        fmt.Printf("Ages %d\n", age)
    }
}

Même si, dans ce cas, il n’est pas judicieux d’afficher les âges de cette manière, il y a des cas où vous n’avez pas besoin de connaître la clé d’un élément. De même, vous pouvez utiliser uniquement la clé de l’élément, comme dans l’exemple suivant :

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for name := range studentsAge {
        fmt.Printf("Names %s\n", name)
    }
}