En Go, un struct est une suite d'éléments nommés appelés champs, et chaque champ possède un nom et un type.
Le nom d'un champ doit être unique au sein du struct.
On peut rapprocher les struct des classes de la programmation orientée objet.
Pour créer un nouveau struct, on utilise les mots-clés type et struct, et on définit explicitement le nom et le type des champs.
Par exemple, on définit ici le struct Shape, qui contient le nom d'une forme et sa taille :
type Shape struct {
name string
size int
}
Les noms de champs dans les struct suivent la convention de Go : les champs dont le nom commence par une minuscule ne sont visibles que par le code du même paquet, tandis que ceux dont le nom commence par une majuscule sont visibles depuis les autres paquets.
Une fois le struct défini, il faut créer une nouvelle instance en définissant les champs par leur nom, dans n'importe quel ordre :
s := Shape {
name: "Square",
size: 25,
}
Pour lire ou modifier les champs d'une instance, on utilise la notation . :
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
Les champs auxquels aucune valeur initiale n'est affectée prennent leur valeur zéro. Par exemple :
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
On peut créer une instance d'un struct sans utiliser les noms des champs, à condition de définir les champs dans l'ordre :
s := Shape {
"Oval",
20,
}
Cependant, cette syntaxe est considérée comme du code fragile, car elle peut casser quand on ajoute un champ, surtout si le nouveau champ est d'un type différent.
Dans l'exemple suivant, on ajoute un champ supplémentaire à Shape :
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
Il est parfois pratique de disposer de fonctions qui nous aident à créer des instances de struct.
Par convention, ces fonctions s'appellent généralement New ou ont un nom qui commence par New, mais comme ce sont de simples fonctions ordinaires, tu peux leur donner le nom que tu veux.
Elles peuvent te rappeler les constructeurs d'autres langages, mais en Go, ce ne sont que des fonctions ordinaires.
Dans l'exemple suivant, une de ces fonctions New sert à créer une nouvelle instance de Shape et à définir automatiquement une valeur par défaut pour la size de la forme :
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
Utiliser des fonctions New présente les avantages suivants :
New sont souvent déclarées dans le même paquet que les struct qu'elles initialisent, elles peuvent même initialiser des champs privés du struct
Dans cet exercice, tu vas organiser des courses entre différents types de voitures télécommandées. Chaque voiture a ses propres caractéristiques de vitesse et de décharge de la batterie.
Les voitures démarrent avec une batterie pleine (100 %). Chaque fois que tu fais avancer la voiture avec la télécommande, elle parcourt une distance en mètres égale à sa vitesse et son pourcentage de batterie restant diminue de sa décharge.
Si la batterie d'une voiture est inférieure à son pourcentage de décharge, tu ne peux plus faire avancer la voiture.
Chaque piste de course a sa propre distance. On teste les voitures en vérifiant si elles peuvent terminer la piste sans épuiser leur batterie.
Définis une structure Car avec les champs de type int suivants :
Pour créer une voiture télécommandée, définis une fonction NewCar qui prend en paramètres la vitesse de la voiture en mètres
et son pourcentage de décharge de batterie (tous deux de type int) et qui renvoie une instance de Car :
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}
Définis une autre structure appelée Track avec le champ distance de type entier.
Pour créer une piste de course, définis une fonction NewTrack qui prend comme unique paramètre la distance de la piste en mètres (de type int) :
distance := 800
track := NewTrack(distance)
// => Track{distance: 800}
Implémente la fonction Drive qui met à jour le nombre de mètres parcourus en fonction de la vitesse de la voiture et qui réduit la batterie en fonction de sa décharge.
S'il n'y a pas assez de batterie pour avancer une fois de plus, la voiture ne bouge pas :
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
Pour terminer une course, une voiture doit être capable de parcourir la distance de la course.
Cela signifie qu'elle ne doit pas épuiser sa batterie avant d'avoir franchi la ligne d'arrivée.
Implémente la fonction CanFinish qui prend en paramètres une instance de Car et une instance de Track et qui renvoie true si la voiture peut terminer la course, et false sinon.
Suppose que tu es sur la ligne de départ de la course et que tu démarres le moteur de la voiture pour la course. Prends en compte le fait que la batterie de la voiture ne sera pas forcément complètement chargée au début de la course :
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
distance := 100
track := NewTrack(distance)
CanFinish(car, track)
// => true
Inscris-toi sur Exercism pour apprendre et maîtriser Go avec 34 concepts165 exercices, et un vrai mentorat humain, le tout gratuitement.