Go ne convertit jamais les types implicitement. Vous convertissez entre types compatibles avec T(v), et entre nombres et texte avec le package strconv. Les deux conversions les plus recherchées :
strconv.Itoa (« integer to ASCII ») formate un int en texte décimal. strconv.Atoi (« ASCII to integer ») analyse du texte en int et renvoie une erreur quand le texte n'est pas un nombre valide. Vérifiez toujours cette erreur.
La conversion T(v)
La syntaxe de conversion de Go ressemble à un appel de fonction portant le nom du type cible. Elle fonctionne dans trois situations :
- entre types numériques (
int,int64,float64,uint8, ...), - entre
stringet[]byteou[]rune, - entre types qui partagent un type sous-jacent (
Celsiusetfloat64).
Lisez attentivement les résultats :
int(3.9)vaut3etint(-3.9)vaut-3. La conversion tronque vers zéro ; elle n'arrondit pas. Utilisez d'abordmath.Round,math.Flooroumath.Ceilpour choisir le comportement.math.Roundarrondit les demis en s'éloignant de zéro, donc-3.5devient-4.uint8(300)vaut44, parce que seuls les 8 bits de poids faible survivent (300 moins 256), etint8(200)vaut-56pour la même raison. Pas d'erreur, pas de panic.Celsiusetfloat64partagent un type sous-jacent, donc ils se convertissent librement, mais seulement explicitement.
Les valeurs sont dans des variables exprès. Avec des constantes, les mêmes conversions ne compilent pas.
Les constantes sont vérifiées, les variables non
Convertir une constante qui ne tient pas dans le type est une erreur de compilation. Convertir une variable de même valeur reboucle silencieusement :
fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8
Convertir une constante non entière vers un type entier est aussi refusé, alors que la même valeur dans une variable est tronquée :
./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int
Si la valeur flottante est hors de la plage du type entier cible (par exemple int64(1e20)), le résultat dépend de l'implémentation : amd64 et arm64, par exemple, donnent des réponses différentes. Vérifiez la plage avant de convertir des valeurs non fiables.
Convertir des nombres en chaînes
| Depuis | Fonction | Exemple | Résultat |
|---|---|---|---|
int | strconv.Itoa(n) | strconv.Itoa(-7) | "-7" |
int64 | strconv.FormatInt(n, base) | strconv.FormatInt(255, 16) | "ff" |
uint64 | strconv.FormatUint(n, base) | strconv.FormatUint(5, 2) | "101" |
float64 | strconv.FormatFloat(f, fmt, prec, 64) | strconv.FormatFloat(3.14159, 'f', 2, 64) | "3.14" |
bool | strconv.FormatBool(b) | strconv.FormatBool(true) | "true" |
| n'importe quoi | fmt.Sprint(v) | fmt.Sprint(3.5) | "3.5" |
| n'importe quoi, formaté | fmt.Sprintf(format, v) | fmt.Sprintf("%05d", 42) | "00042" |
FormatFloat prend un octet de format ('f' pour la notation fixe, 'e' pour l'exposant, 'g' pour la plus courte des deux), une précision (-1 signifie « le moins de chiffres possible pour un aller-retour exact »), et la taille en bits du flottant d'origine (64 ou 32).
strconv est plus rapide que fmt.Sprint, qui emballe la valeur dans une interface et passe par le chemin de formatage général de fmt. Dans une boucle critique, cette différence se voit ; pour des conversions occasionnelles, prenez ce qui se lit le mieux.
Convertir des chaînes en nombres
| Vers | Fonction | Renvoie |
|---|---|---|
int | strconv.Atoi(s) | int, error |
| tout entier signé | strconv.ParseInt(s, base, bitSize) | int64, error |
| tout entier non signé | strconv.ParseUint(s, base, bitSize) | uint64, error |
| flottant | strconv.ParseFloat(s, bitSize) | float64, error |
| bool | strconv.ParseBool(s) | bool, error |
ParseInt renvoie toujours un int64. L'argument bitSize (0, 8, 16, 32, 64) fixe la plage acceptée, donc le résultat est garanti de tenir quand vous le convertissez vers un type plus petit. Une base de 0 signifie « déduire du préfixe », donc 0x1f, 0o17, 0b101 et 1_000 sont tous analysés.
Ce que montre la sortie :
" 42"échoue.Atoiaccepte un signe facultatif et des chiffres, rien d'autre. Une entrée lue avecbufiose termine généralement par\n, donc retirez-le."4.2"est invalide pourAtoi. UtilisezParseFloatpour les décimaux.- Sur une erreur de dépassement,
ParseIntrenvoie la plus grande valeur qui tient (127pourint8) avec l'erreur. N'utilisez pas la valeur quand l'erreur n'est pas nil. - Les erreurs sont des valeurs
*strconv.NumErrorqui enveloppentstrconv.ErrSyntaxoustrconv.ErrRange, doncerrors.Ispeut les distinguer.
ParseBool accepte 1, t, T, TRUE, true, True et les formes fausses correspondantes. "yes" et "on" sont des erreurs.
Le piège de string(65)
Convertir un entier en string ne produit pas de chiffres. Cela produit le caractère de ce point de code Unicode :
n := 65
s := string(n) // "A", not "65"
Le compilateur l'accepte, mais go vet le signale :
./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits
Si vous voulez vraiment le caractère, dites-le avec une rune : string(rune(n)). Si vous voulez le nombre sous forme de texte, utilisez strconv.Itoa(n). Convertir une rune ou un byte en string est correct et courant :
Chaînes, octets et runes
string, []byte et []rune se convertissent les uns dans les autres avec T(v). Chaque conversion copie les données, parce que les chaînes sont immuables et que les slices ne le sont pas :
Convertissez en []rune quand vous devez indexer ou modifier par caractère ; convertissez en []byte pour les E/S, le hachage et les modifications au niveau des octets. La page runes et octets détaille l'UTF-8.
Conversion ou assertion de type
Une conversion fait passer une valeur d'un type concret à un autre. Récupérer la valeur concrète d'une interface (any, error, io.Reader) est une opération différente, l'assertion de type :
var v any = 42
n := v.(int) // type assertion: v holds an int, give it to me
f := float64(n) // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
// // to type float64: need type assertion
Faites d'abord l'assertion, puis convertissez. La forme comma-ok n, ok := v.(int) évite un panic quand le type est faux.
Référence rapide
| Tâche | Code |
|---|---|
| int en string | strconv.Itoa(n) |
| int64 en string | strconv.FormatInt(n, 10) |
| string en int | n, err := strconv.Atoi(s) |
| string en int64 | n, err := strconv.ParseInt(s, 10, 64) |
| string en float64 | f, err := strconv.ParseFloat(s, 64) |
| float64 en string | strconv.FormatFloat(f, 'f', -1, 64) |
| float64 en int | int(f) (tronque) ou int(math.Round(f)) |
| int en float64 | float64(n) |
| string en []byte | []byte(s) |
| []byte en string | string(b) |
| rune en string | string(r) |
| bool en string | strconv.FormatBool(b) |
| n'importe quelle valeur en string | fmt.Sprint(v) |
Questions fréquentes
Comment convertir un int en string en Go ?
Utilisez strconv.Itoa(n) : strconv.Itoa(42) renvoie "42". Pour un int64, utilisez strconv.FormatInt(n, 10). fmt.Sprint(n) fonctionne aussi pour n'importe quel type mais il est plus lent. N'écrivez pas string(n) : cela traite n comme un point de code Unicode, donc string(65) vaut "A".
Comment convertir une string en int en Go ?
Utilisez strconv.Atoi, qui renvoie le nombre et une erreur :
n, err := strconv.Atoi("42")
if err != nil {
// not a valid integer
}
Pour une taille ou une base précise, utilisez strconv.ParseInt(s, 10, 64), qui renvoie un int64. Atoi ne retire pas les espaces, donc " 42" est une erreur ; appelez d'abord strings.TrimSpace.
Comment faire un cast en Go ?
Go appelle cela une conversion, et la syntaxe est T(v) : float64(n), int(f), []byte(s). Elle fonctionne entre types numériques, entre chaînes et slices d'octets ou de runes, et entre types ayant le même type sous-jacent. Elle n'analyse pas du texte : transformer "42" en 42 demande strconv. Récupérer un type concret depuis une interface est une assertion de type, v.(T), pas une conversion.
Comment convertir un float en int en Go ?
int(f) tronque vers zéro : int(3.9) vaut 3 et int(-3.9) vaut -3. Pour arrondir, utilisez int(math.Round(f)). Si le flottant est hors de la plage du type entier, le résultat dépend de l'implémentation, donc vérifiez d'abord la plage quand la valeur vient d'une entrée.
Pourquoi string(65) renvoie-t-il « A » en Go ?
Convertir un entier en string l'interprète comme un point de code Unicode, et 65 est le point de code de A. go vet le signale : conversion from int to string yields a string of one rune, not a string of digits. Utilisez strconv.Itoa(65) pour obtenir "65".