Parcours
/
Go
Go
/
Exercices
/
Salle de tri
Salle de tri

Salle de tri

Exercice d'apprentissage

Introduction

Conversion de types

Go exige une conversion explicite entre les différents types. La conversion entre types (aussi appelée type casting) se fait via une fonction portant le nom du type vers lequel convertir. Par exemple, pour convertir un int en float64, il faut faire ce qui suit :

var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)

Conversion entre types primitifs et strings

Il existe un paquet strconv pour convertir entre types primitifs (comme int) et string.

import "strconv"

var intString string = "42"
var i, err = strconv.Atoi(intString)

var number int = 12
var s string = strconv.Itoa(number)

Assertions de type

Les interfaces en Go peuvent introduire une ambiguïté sur le type sous-jacent. Une assertion de type permet d'extraire la valeur concrète sous-jacente d'une valeur d'interface en utilisant cette syntaxe : interfaceVariable.(concreteType).

Par exemple :

var input any = 12
number := input.(int)

NOTE : cela provoquera un panic si la variable d'interface ne contient pas une valeur du type concret.

On peut tester si une valeur d'interface contient un type concret spécifique en utilisant les deux valeurs de retour de l'assertion de type : la valeur sous-jacente et une valeur booléenne qui indique si l'assertion a réussi. Par exemple :

str, ok := input.(string) // no panic if input is not a string

Si input contient une string, alors str sera la valeur sous-jacente et ok sera vrai. Si input ne contient pas de string, alors str sera la valeur zéro du type string (c'est-à-dire "", la chaîne vide) et ok sera faux. Dans tous les cas, aucun panic ne se produit.

Type switches

Un type switch peut effectuer plusieurs assertions de type en série. Il a la même syntaxe qu'une assertion de type (interfaceVariable.(concreteType)), mais le concreteType est remplacé par le mot-clé type. Voici un exemple :

var i any = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}

switch v := i.(type) {
case int:
    fmt.Printf("the integer %d\n", v)
case string:
    fmt.Printf("the string %s\n", v)
default:
    fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}

Instructions

Jen travaille dans la salle de tri d'une grande usine. La salle de tri doit traiter tout ce qui y entre en le classant à l'aide d'une étiquette. Jen s'occupe des éléments pré-classés comme des nombres et a besoin d'un programme pour l'aider à trier.

La plupart des valeurs primitives doivent recevoir des étiquettes simples. Pour les nombres, elle veut des strings qui disent "This is the number 2.0" (si le nombre valait 2). Jen veut la même sortie pour les entiers et les nombres décimaux.

Il y a quelques interfaces Box qu'il faut déballer pour en récupérer le contenu. Pour un NumberBox, elle veut des strings qui disent "This is a box containing the number 3.0" (si la méthode Number() renvoie 3). Pour un FancyNumberBox, elle veut des strings qui disent "This is a fancy box containing the number 4.0", mais uniquement si le type est un FancyNumber.

Tout ce qui est inattendu doit renvoyer "Return to sender", pour que Jen puisse le renvoyer là d'où il vient.

1. Décris les nombres simples

Jen veut que les nombres renvoient des strings comme "This is the number 2.0" (avec un chiffre après la virgule) :

fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3

2. Décris une boîte de nombres

Jen veut que les boîtes de nombres renvoient des strings comme "This is a box containing the number 2.0" (là encore, avec un chiffre après la virgule) :

fmt.Println(DescribeNumberBox(numberBoxContaining{12}))
// Output: This is a box containing the number 12.0

3. Implémente une méthode qui extrait le nombre d'une boîte de nombres sophistiquée

Jen a besoin d'une fonction auxiliaire pour extraire le nombre d'un FancyNumberBox. Si le FancyNumberBox est un FancyNumber, extrais sa valeur et convertis-la d'un string en un int. Tout autre type de FancyNumberBox doit renvoyer 0.

fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0

4. Décris une boîte de nombres sophistiquée

Si le FancyNumberBox est un FancyNumber, Jen veut des strings qui disent "This is a fancy box containing the number 4.0". Tout autre type de FancyNumberBox doit dire "This is a fancy box containing the number 0.0".

fmt.Println(DescribeFancyNumberBox(FancyNumber{"10"}))
// Output: This is a fancy box containing the number 10.0
fmt.Println(DescribeFancyNumberBox(AnotherFancyNumber{"4"}))
// Output: This is a fancy box containing the number 0.0

REMARQUE : il faut utiliser la fonction ExtractFancyNumber !

5. Implémente DescribeAnything qui les utilise toutes

C'est la fonction principale dont Jen a besoin, celle qui prend n'importe quelle entrée. DescribeAnything doit déléguer aux autres fonctions selon le type de la valeur passée en argument. Plus précisément :

  • int et float64 doivent tous les deux déléguer à DescribeNumber
  • NumberBox doit déléguer à DescribeNumberBox
  • FancyNumberBox doit déléguer à DescribeFancyNumberBox
  • tout le reste doit donner "Return to sender"
fmt.Println(DescribeAnything(numberBoxContaining{12.345}))
// Output: This is a box containing the number 12.3
fmt.Println(DescribeAnything("some string"))
// Output: Return to sender
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Go Exercism

Prêt à commencer Salle de tri ?

Inscris-toi sur Exercism pour apprendre et maîtriser Go avec 34 concepts165 exercices, et un vrai mentorat humain, le tout gratuitement.