Introduction
Les types de données spécifient les types de valeurs que les variables particulières stockeront lorsque vous écrivez un programme. Le type de données détermine également les opérations qui peuvent être effectuées sur les données.
Dans cet article, nous aborderons les types de données importants natifs de Go. Ce n’est pas une investigation exhaustive des types de données, mais cela vous aidera à vous familiariser avec les options disponibles en Go. Comprendre certains types de données de base vous permettra d’écrire un code plus clair et qui s’exécute efficacement.
Contexte
Une façon de penser aux types de données est de considérer les différents types de données que nous utilisons dans le monde réel. Un exemple de données dans le monde réel sont les nombres : nous pouvons utiliser des nombres entiers (0, 1, 2, …), des entiers (…, -1, 0, 1, …), et des nombres irrationnels (π), par exemple.
Habituellement, en mathématiques, nous pouvons combiner des nombres de différents types et obtenir une sorte de réponse. Nous pouvons vouloir ajouter 5 à π, par exemple :
5 + π
Nous pouvons soit garder l’équation comme réponse pour tenir compte du nombre irrationnel, soit arrondir π à un nombre avec un nombre réduit de décimales, puis additionner les nombres ensemble :
5 + π = 5 + 3.14 = 8.14
Mais, si nous commençons à essayer d’évaluer des nombres avec un autre type de données, comme des mots, les choses deviennent moins sensées. Comment résoudrions-nous l’équation suivante ?
shark + 8
Pour les ordinateurs, chaque type de données est assez différent—comme les mots et les nombres. Par conséquent, nous devons faire attention à la manière dont nous utilisons différents types de données pour attribuer des valeurs et comment nous les manipulons à travers des opérations.
Entiers
Comme en mathématiques, les entiers en programmation informatique sont des nombres entiers qui peuvent être positifs, négatifs ou 0 (…, -1, 0, 1, …). En Go, un entier est connu sous le nom d’ int
. Comme dans d’autres langages de programmation, vous ne devez pas utiliser de virgules dans les nombres de quatre chiffres ou plus, donc lorsque vous écrivez 1 000 dans votre programme, écrivez-le comme 1000
.
Nous pouvons imprimer un entier de manière simple comme ceci :
Output-459
Ou, nous pouvons déclarer une variable, qui dans ce cas est un symbole du nombre que nous utilisons ou manipulons, comme ceci :
Output-459
Nous pouvons également faire des mathématiques avec des entiers en Go. Dans le bloc de code suivant, nous utiliserons l’opérateur d’affectation :=
pour déclarer et instancier la variable sum
:
Output48
Comme le montre la sortie, l’opérateur mathématique -
a soustrait l’entier 68
de 116
, ce qui a donné 48
. Vous en apprendrez plus sur la déclaration des variables dans la section Déclaration des types de données pour les variables.
Les entiers peuvent être utilisés de nombreuses façons dans les programmes Go. Au fur et à mesure que vous apprenez Go, vous aurez de nombreuses occasions de travailler avec des entiers et d’approfondir vos connaissances sur ce type de données.
Nombres à virgule flottante
Un nombre à virgule flottante ou un float est utilisé pour représenter les nombres réels qui ne peuvent pas être exprimés en tant qu’entiers. Les nombres réels incluent tous les nombres rationnels et irrationnels, et pour cette raison, les nombres à virgule flottante peuvent contenir une partie fractionnaire, comme 9,0 ou -116,42. Pour les besoins de la réflexion sur un float dans un programme Go, il s’agit d’un nombre qui contient un point décimal.
Comme nous l’avons fait avec les entiers, nous pouvons afficher un nombre à virgule flottante de manière simple comme ceci :
Output-459.67
Nous pouvons également déclarer une variable qui représente un float, comme ceci :
Output-459.67
Tout comme avec les entiers, nous pouvons effectuer des opérations mathématiques avec des floats en Go, aussi :
Output929.24
Avec les entiers et les nombres à virgule flottante, il est important de garder à l’esprit que 3 ≠ 3,0, car 3 fait référence à un entier tandis que 3,0 fait référence à un float.
Tailles des types numériques
En plus de la distinction entre les entiers et les flottants, Go possède deux types de données numériques qui sont distingués par la nature statique ou dynamique de leurs tailles. Le premier type est un type indépendant de l’architecture, ce qui signifie que la taille des données en bits ne change pas, quel que soit la machine sur laquelle le code est exécuté.
La plupart des architectures système aujourd’hui sont soit 32 bits, soit 64 bits. Par exemple, vous pourriez développer pour un ordinateur portable Windows moderne, sur lequel le système d’exploitation fonctionne sur une architecture 64 bits. Cependant, si vous développez pour un dispositif comme une montre connectée, vous pourriez travailler avec une architecture 32 bits. Si vous utilisez un type indépendant de l’architecture comme int32
, quel que soit l’architecture pour laquelle vous compilez, le type aura une taille constante.
Le second type est un type spécifique à l’implémentation. Dans ce type, la taille en bits peut varier en fonction de l’architecture sur laquelle le programme est construit. Par exemple, si nous utilisons le type int
, lorsque Go compile pour une architecture 32 bits, la taille du type de données sera de 32 bits. Si le programme est compilé pour une architecture 64 bits, la variable sera de 64 bits.
En plus des types de données ayant des tailles différentes, les types comme les entiers sont également disponibles en deux types de base : signés et non signés. Un int8
est un entier signé, et peut avoir une valeur de -128 à 127. Un uint8
est un entier non signé, et ne peut avoir qu’une valeur positive de 0 à 255.
Les plages sont basées sur la taille en bits. Pour les données binaires, 8 bits peuvent représenter un total de 256 valeurs différentes. Parce qu’un type int
doit supporter à la fois des valeurs positives et négatives, un entier de 8 bits (int8
) aura une plage de -128 à 127, pour un total de 256 valeurs uniques possibles.
Go a les types entiers indépendants de l’architecture suivants :
uint8 unsigned 8-bit integers (0 to 255)
uint16 unsigned 16-bit integers (0 to 65535)
uint32 unsigned 32-bit integers (0 to 4294967295)
uint64 unsigned 64-bit integers (0 to 18446744073709551615)
int8 signed 8-bit integers (-128 to 127)
int16 signed 16-bit integers (-32768 to 32767)
int32 signed 32-bit integers (-2147483648 to 2147483647)
int64 signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
Les flottants et les nombres complexes sont également disponibles en différentes tailles :
float32 IEEE-754 32-bit floating-point numbers
float64 IEEE-754 64-bit floating-point numbers
complex64 complex numbers with float32 real and imaginary parts
complex128 complex numbers with float64 real and imaginary parts
Il existe également quelques types numériques alias, qui attribuent des noms utiles à des types de données spécifiques :
byte alias for uint8
rune alias for int32
Le but de l’alias byte
est de rendre clair quand votre programme utilise des octets comme mesure courante en informatique dans les éléments de chaînes de caractères, par opposition à de petits entiers non liés à la mesure des données d’octets. Bien que byte
et uint8
soient identiques une fois le programme compilé, byte
est souvent utilisé pour représenter des données de caractères sous forme numérique, tandis que uint8
est destiné à être un nombre dans votre programme.
L’alias rune
est un peu différent. Alors que byte
et uint8
sont exactement les mêmes données, une rune
peut être un seul octet ou quatre octets, une plage déterminée par int32
. Une rune
est utilisée pour représenter un caractère Unicode, alors que seuls les caractères ASCII peuvent être représentés uniquement par un type de données int32
.
En outre, Go a les types spécifiques à l’implémentation suivants :
uint unsigned, either 32 or 64 bits
int signed, either 32 or 64 bits
uintptr unsigned integer large enough to store the uninterpreted bits of a pointer value
Les types spécifiques à l’implémentation auront leur taille définie par l’architecture pour laquelle le programme est compilé.
Choisir les types de données numériques
Choisir la taille appropriée a généralement plus à voir avec les performances pour l’architecture cible pour laquelle vous programmez que la taille des données avec lesquelles vous travaillez. Cependant, sans avoir besoin de connaître les implications spécifiques en termes de performance pour votre programme, vous pouvez suivre certaines de ces directives de base lorsque vous commencez.
Comme discuté précédemment dans cet article, il existe des types indépendants de l’architecture et des types spécifiques à l’implémentation. Pour les données entières, il est courant en Go d’utiliser les types d’implémentation comme int
ou uint
plutôt que int64
ou uint64
. Cela se traduira généralement par la vitesse de traitement la plus rapide pour votre architecture cible. Par exemple, si vous utilisez un int64
et compilez pour une architecture 32 bits, cela prendra au moins deux fois plus de temps pour traiter ces valeurs car cela nécessite des cycles CPU supplémentaires pour déplacer les données à travers l’architecture. Si vous aviez utilisé un int
à la place, le programme le définirait comme une taille de 32 bits pour une architecture 32 bits, et serait considérablement plus rapide à traiter.
Si vous savez que vous n’atteindrez pas une plage de taille spécifique, alors choisir un type indépendant de l’architecture peut à la fois augmenter la vitesse et diminuer l’utilisation de la mémoire. Par exemple, si vous savez que vos données ne dépasseront pas la valeur de 100
et ne seront que des nombres positifs, alors choisir un uint8
rendra votre programme plus efficace car il nécessitera moins de mémoire.
Maintenant que nous avons examiné certaines des plages possibles pour les types de données numériques, examinons ce qui se passe si nous dépassons ces plages dans notre programme.
Dépassement vs. Retour à zéro
Go a le potentiel de dépasser un nombre et de revenir à zéro un nombre lorsque vous essayez de stocker une valeur plus grande que le type de données était conçu pour stocker, selon que la valeur est calculée au moment de la compilation ou au moment de l’exécution. Une erreur de compilation se produit lorsque le programme détecte une erreur lorsqu’il tente de construire le programme. Une erreur d’exécution se produit après la compilation du programme, pendant qu’il s’exécute.
Dans l’exemple suivant, nous définissons maxUint32
à sa valeur maximale:
Il compilera et s’exécutera avec le résultat suivant:
Si nous ajoutons 1
à la valeur au moment de l’exécution, elle reviendra à 0
:
En revanche, modifions le programme pour ajouter 1
à la variable lorsque nous l’assignons, avant la compilation:
Au moment de la compilation, si le compilateur peut déterminer qu’une valeur sera trop grande pour être contenue dans le type de données spécifié, il lancera une erreur de dépassement
. Cela signifie que la valeur calculée est trop grande pour le type de données que vous avez spécifié.
Parce que le compilateur peut déterminer qu’il dépassera la valeur, il lancera maintenant une erreur:
Outputprog.go:6:36: constant 4294967296 overflows uint32
Comprendre les limites de vos données vous aidera à éviter des bogues potentiels dans votre programme à l’avenir.
Maintenant que nous avons abordé les types numériques, examinons comment stocker des valeurs booléennes.
Booléens
Le type de données booléen peut prendre l’une des deux valeurs, soit true
ou false
, et est défini comme bool
lors de sa déclaration en tant que type de données. Les booléens sont utilisés pour représenter les valeurs de vérité associées à la branche logique des mathématiques, qui informe les algorithmes en informatique.
Les valeurs true
et false
seront toujours avec un ‘t’ minuscule et un ‘f’ minuscule respectivement, car ce sont des identificateurs prédéclarés en Go.
De nombreuses opérations en mathématiques nous donnent des réponses qui évaluent soit à vrai, soit à faux:
- supérieur à
- 500 > 100 true
- 1 > 5 false
- inférieur à
- 200 < 400 true
- 4 < 2 false
- égal
- 5 = 5 true
- 500 = 400 false
Comme avec les nombres, nous pouvons stocker une valeur booléenne dans une variable:
Nous pouvons ensuite afficher la valeur booléenne en appelant la fonction fmt.Println()
:
Comme 5
n’est pas supérieur à 8
, nous obtiendrons la sortie suivante:
Outputfalse
Au fur et à mesure que vous écrivez plus de programmes en Go, vous vous familiariserez davantage avec le fonctionnement des booléens et avec la manière dont différentes fonctions et opérations qui évaluent à true
ou false
peuvent changer le cours du programme.
Chaînes de caractères
Une chaîne de caractères est une séquence d’un ou plusieurs caractères (lettres, chiffres, symboles) qui peut être une constante ou une variable. Les chaînes existent soit entre guillemets simples `
soit entre guillemets doubles "
en Go et ont des caractéristiques différentes en fonction des guillemets utilisés.
Si vous utilisez les guillemets simples, vous créez un littéral de chaîne brut. Si vous utilisez les guillemets doubles, vous créez un littéral de chaîne interprété.
Littéraux de Chaîne Bruts
Les littéraux de chaîne bruts sont des séquences de caractères entre guillemets simples, souvent appelés back ticks. Entre les guillemets, tout caractère apparaîtra tel qu’il est affiché entre les guillemets simples, à l’exception du caractère guillemet simple lui-même.
OutputSay "hello" to Go!
Habituellement, les barres obliques inverses sont utilisées pour représenter des caractères spéciaux dans les chaînes de caractères. Par exemple, dans une chaîne interprétée, \n
représenterait un saut de ligne dans une chaîne. Cependant, les barres obliques inverses n’ont aucune signification particulière à l’intérieur des littéraux de chaîne brutes :
Parce que la barre oblique inverse n’a pas de signification spéciale dans un littéral de chaîne, elle affichera en fait la valeur de \n
au lieu de créer un saut de ligne :
OutputSay "hello" to Go!\n
Les littéraux de chaîne brutes peuvent également être utilisés pour créer des chaînes multilignes :
OutputThis string is on
multiple lines
within a single back
quote on either side.
Dans les blocs de code précédents, les sauts de ligne ont été transmis littéralement de l’entrée à la sortie.
Littéraux de Chaîne Interprétés
Les littéraux de chaîne interprétés sont des séquences de caractères entre guillemets doubles, comme dans "bar"
. Entre les guillemets, tout caractère peut apparaître à l’exception du saut de ligne et des guillemets doubles non échappés. Pour afficher des guillemets doubles dans une chaîne interprétée, vous pouvez utiliser la barre oblique inverse comme caractère d’échappement, comme ceci :
OutputSay "hello" to Go!
Vous utiliserez presque toujours des littéraux de chaîne interprétés car ils permettent l’utilisation de caractères d’échappement à l’intérieur. Pour plus d’informations sur l’utilisation des chaînes de caractères, consultez Une Introduction à l’Utilisation des Chaînes de Caractères en Go.
Chaînes de caractères avec des caractères UTF-8
UTF-8 est un schéma d’encodage utilisé pour encoder des caractères de largeur variable en un à quatre octets. Go prend en charge les caractères UTF-8 prêts à l’emploi, sans configuration spéciale, bibliothèques ou packages. Les caractères romains tels que la lettre A
peuvent être représentés par une valeur ASCII comme le nombre 65. Cependant, avec des caractères spéciaux comme un caractère international de 世
, UTF-8 serait nécessaire. Go utilise le type alias rune
pour les données UTF-8.
Vous pouvez utiliser le mot-clé range
dans une boucle for
pour indexer à travers n’importe quelle chaîne en Go, même une chaîne UTF-8. Les boucles for
et range
seront abordées plus en détail plus tard dans la série ; pour l’instant, il est important de savoir que nous pouvons utiliser cela pour compter les octets dans une chaîne donnée :
Dans le bloc de code ci-dessus, nous avons déclaré la variable a
et lui avons attribué la valeur de Hello, 世界
. Le texte attribué contient des caractères UTF-8.
Nous avons ensuite utilisé une boucle for
standard ainsi que le mot-clé range
. En Go, le mot-clé range
indexera à travers une chaîne en renvoyant un caractère à la fois, ainsi que l’index d’octet où se trouve le caractère dans la chaîne.
En utilisant la fonction fmt.Printf
, nous avons fourni une chaîne de format de %d: %s\n
. %d
est le verbe d’impression pour un chiffre (dans ce cas, un entier), et %s
est le verbe d’impression pour une chaîne. Nous avons ensuite fourni les valeurs de i
, qui est l’indice courant de la boucle for
, et c
, qui est le caractère courant dans la boucle for
.
Enfin, nous avons affiché la longueur totale de la variable a
en utilisant la fonction intégrée len
.
Plus tôt, nous avons mentionné qu’un rune est un alias pour int32
et peut être composé d’un à quatre octets. Le caractère 世
prend trois octets pour être défini et l’indice avance en conséquence lorsqu’on parcourt la chaîne UTF-8. C’est la raison pour laquelle i
n’est pas séquentiel lorsqu’il est imprimé.
Output0: H
1: e
2: l
3: l
4: o
5: ,
6:
7: 世
10: 界
length of 'Hello, 世界': 13
Comme vous pouvez le voir, la longueur est plus longue que le nombre de fois qu’il a fallu parcourir la chaîne.
Vous ne travaillerez pas toujours avec des chaînes UTF-8, mais lorsque vous le ferez, vous comprendrez maintenant pourquoi ce sont des runes et non un simple int32
.
Déclaration des Types de Données pour les Variables
Maintenant que vous connaissez les différents types de données primitifs, nous allons voir comment attribuer ces types aux variables en Go.
En Go, nous pouvons définir une variable avec le mot-clé var
suivi du nom de la variable et du type de données souhaité.
Dans l’exemple suivant, nous allons déclarer une variable appelée pi
de type float64
.
Le mot-clé var
est la première chose déclarée :
Suivi du nom de notre variable, pi
:
Et enfin le type de données float64
:
Nous pouvons également spécifier une valeur initiale si nous le souhaitons, comme 3.14
:
Go est un langage statiquement typé. Statiquement typé signifie que chaque instruction dans le programme est vérifiée à la compilation. Cela signifie également que le type de données est lié à la variable, alors que dans les langages à liaison dynamique, le type de données est lié à la valeur.
Par exemple, en Go, le type est déclaré lors de la déclaration d’une variable :
Chacune de ces variables pourrait être d’un type de données différent si vous les aviez déclarées différemment.
Cela est différent d’un langage comme PHP, où le type de données est associé à la valeur :
Dans le bloc de code précédent, le premier $s
est une chaîne de caractères parce qu’il est assigné à la valeur "sammy"
, et le second est un entier parce qu’il a la valeur 123
.
Ensuite, examinons des types de données plus complexes comme les tableaux.
Tableaux
Un tableau est une séquence ordonnée d’éléments. La capacité d’un tableau est définie lors de sa création. Une fois qu’un tableau a alloué sa taille, celle-ci ne peut plus être modifiée. Comme la taille d’un tableau est statique, cela signifie qu’il n’alloue la mémoire qu’une seule fois. Cela rend les tableaux quelque peu rigides à utiliser, mais augmente les performances de votre programme. Pour cette raison, les tableaux sont généralement utilisés lors de l’optimisation des programmes. Tranches, abordées ensuite, sont plus flexibles et constituent ce que l’on pourrait considérer comme des tableaux dans d’autres langages.
Les tableaux sont définis en déclarant la taille du tableau, puis le type de données avec les valeurs définies entre accolades { }
.
Un tableau de chaînes de caractères ressemble à ceci :
Nous pouvons stocker un tableau dans une variable et l’afficher :
Output[blue coral staghorn coral pillar coral]
Comme mentionné précédemment, les tranches sont similaires aux tableaux, mais sont beaucoup plus flexibles. Examinons ce type de données mutable.
Tranches
Une tranche est une séquence ordonnée d’éléments dont la longueur peut varier. Les tranches peuvent augmenter leur taille de manière dynamique. Lorsque vous ajoutez de nouveaux éléments à une tranche, si celle-ci n’a pas suffisamment de mémoire pour stocker les nouveaux éléments, elle demandera plus de mémoire au système selon les besoins. Comme une tranche peut être étendue pour ajouter plus d’éléments si nécessaire, elles sont plus couramment utilisées que les tableaux.
Les séquences sont définies en déclarant le type de données précédé par des parenthèses ouvrantes et fermantes []
et en indiquant les valeurs entre des accolades { }
.
Un morceau d’entiers se présente ainsi:
Un morceau de flottants se présente ainsi:
Un morceau de chaînes se présente ainsi:
Laisons notre définition de morceau de chaînes comme seaCreatures
:
Nous pouvons l’afficher en appelant la variable:
La sortie sera exactement comme la liste que nous avons créée:
Output[shark cuttlefish squid mantis shrimp]
Nous pouvons utiliser la clé append
pour ajouter un élément à notre morceau. La commande suivante ajoutera la valeur de chaîne de seahorse
au morceau:
Vous pouvez verifier qu’il a été ajouté en l’affichant:
Output[shark cuttlefish squid mantis shrimp seahorse]
Comme vous pouvez le voir, si vous avez besoin de gérer une taille inconnue d’éléments, une séquence sera plus souple que une liste.
Les cartes
Le map est un type de tableau hash ou dictionnaire intégré dans Go. Les cartes utilisent les clés et les valeurs comme paire pour stocker des données. Cela est utile en programmation pour trouver rapidement une valeur par un index, ou bien ici, par une clé. Par exemple, vous pouvez souhaiter garder une map de utilisateurs, indexée par leur identifiant d’utilisateur. La clé serait l’identifiant d’utilisateur, et l’objet utilisateur serait la valeur. Une map est construite avec la syntaxe map
suivie du type de données des clés en parenthèses ouvrantes et fermantes [ ]
, puis du type de données des valeurs et des paires de clés entre des accolades.
map[key]value{}
Traditionnellement, les données qui sont liées sont stockées dans un dictionnaire comme ceci :
Vous pouvez remarquer que, en plus des accrocheurs et des crochets, il y a également des points de colonnes tout au long du dictionnaire. Les mots à gauche des colons sont les clés. Les clés peuvent être n’importe quel type comparable en Go. Les types comparables sont des types primitifs tels que strings
, ints
, etc. Un type primitif est défini par la langue de programmation, et non construit par combiner d’autres types. Bien que ce soit une pratique recommandée de les garder simples pour éviter des erreurs de programmation, il est considéré comme meilleure pratique de les garder simples. Les clés du dictionnaire ci-dessus sont : name
, animal
, color
, et location
.
Les mots à droite des colons sont les valeurs. Les valeurs peuvent être composées de tous les types de données. Les valeurs dans le dictionnaire ci-dessus sont : Sammy
, shark
, blue
, et ocean
.
Lets store the map inside a variable and print it out:
Outputmap[animal:shark color:blue location:ocean name:Sammy]
If we want to isolate Sammy’s color, we can do so by calling sammy["color"]
. Let’s print that out:
Outputblue
As maps offer key-value pairs for storing data, they can be important elements in your Go program.
Conclusion
À ce stade, vous devriez avoir une meilleure compréhension de certains des principaux types de données disponibles pour vous utiliser en Go. Chacun de ces types de données deviendra important à mesure que vous développerez des projets de programmation dans le langage Go.
Une fois que vous avez une bonne maîtrise des types de données disponibles en Go, vous pouvez apprendre Comment Convertir les Types de Données afin de modifier vos types de données en fonction de la situation.
Source:
https://www.digitalocean.com/community/tutorials/understanding-data-types-in-go