Go konvertiert Typen nie implizit. Zwischen kompatiblen Typen konvertierst du mit T(v), zwischen Zahlen und Text mit dem Paket strconv. Die beiden meistgesuchten Konvertierungen:
strconv.Itoa („integer to ASCII“) formatiert ein int als Dezimaltext. strconv.Atoi („ASCII to integer“) parst Text in ein int und gibt einen Fehler zurück, wenn der Text keine gültige Zahl ist. Prüf diesen Fehler immer.
Die Konvertierung T(v)
Die Syntax für Konvertierungen in Go sieht aus wie ein Funktionsaufruf, benannt nach dem Zieltyp. Sie funktioniert in drei Situationen:
- zwischen numerischen Typen (
int,int64,float64,uint8, ...), - zwischen
stringund[]byteoder[]rune, - zwischen Typen, die sich einen zugrunde liegenden Typ teilen (
Celsiusundfloat64).
Sieh dir die Ergebnisse genau an:
int(3.9)ist3undint(-3.9)ist-3. Die Konvertierung schneidet in Richtung null ab; sie rundet nicht. Nimm vorhermath.Round,math.Floorodermath.Ceil, um das Verhalten zu wählen.math.Roundrundet bei ,5 von null weg, also wird-3.5zu-4.uint8(300)ist44, weil nur die unteren 8 Bit übrig bleiben (300 minus 256), undint8(200)ist aus demselben Grund-56. Kein Fehler, keine Panic.Celsiusundfloat64teilen sich einen zugrunde liegenden Typ, also lassen sie sich frei konvertieren, aber nur explizit.
Die Werte stehen absichtlich in Variablen. Mit Konstanten kompilieren dieselben Konvertierungen nicht.
Konstanten werden geprüft, Variablen nicht
Eine Konstante zu konvertieren, die nicht passt, ist ein Compilerfehler. Eine Variable mit demselben Wert zu konvertieren läuft still über:
fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8
Auch eine nicht ganzzahlige Konstante in einen Ganzzahltyp zu konvertieren wird abgelehnt, während derselbe Wert in einer Variablen abgeschnitten wird:
./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int
Liegt der Float-Wert außerhalb des Bereichs des Ganzzahl-Zieltyps (etwa int64(1e20)), ist das Ergebnis implementierungsabhängig: amd64 und arm64 liefern zum Beispiel verschiedene Antworten. Prüf den Bereich, bevor du nicht vertrauenswürdige Werte konvertierst.
Zahlen in Strings konvertieren
| Von | Funktion | Beispiel | Ergebnis |
|---|---|---|---|
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" |
| beliebig | fmt.Sprint(v) | fmt.Sprint(3.5) | "3.5" |
| beliebig, formatiert | fmt.Sprintf(format, v) | fmt.Sprintf("%05d", 42) | "00042" |
FormatFloat nimmt ein Format-Byte ('f' für Festkomma, 'e' für Exponent, 'g' für die kürzere Variante), eine Genauigkeit (-1 bedeutet „die wenigsten Ziffern, die sich exakt zurückverwandeln lassen“) und die Bitgröße des ursprünglichen Floats (64 oder 32).
strconv ist schneller als fmt.Sprint, das den Wert in ein Interface packt und den allgemeinen Formatierungspfad von fmt durchläuft. In einer heißen Schleife macht sich das bemerkbar; bei gelegentlichen Konvertierungen nimm, was sich besser liest.
Strings in Zahlen konvertieren
| Nach | Funktion | Gibt zurück |
|---|---|---|
int | strconv.Atoi(s) | int, error |
| jeder vorzeichenbehaftete int | strconv.ParseInt(s, base, bitSize) | int64, error |
| jeder vorzeichenlose int | strconv.ParseUint(s, base, bitSize) | uint64, error |
| float | strconv.ParseFloat(s, bitSize) | float64, error |
| bool | strconv.ParseBool(s) | bool, error |
ParseInt gibt immer ein int64 zurück. Das Argument bitSize (0, 8, 16, 32, 64) legt den akzeptierten Bereich fest, also passt das Ergebnis garantiert, wenn du es herunterkonvertierst. base 0 bedeutet „aus dem Präfix ableiten“, also werden 0x1f, 0o17, 0b101 und 1_000 alle geparst.
Was die Ausgabe zeigt:
" 42"scheitert.Atoiakzeptiert ein optionales Vorzeichen und Ziffern, sonst nichts. Eingaben ausbufioenden meist mit\n, also kürze sie vorher."4.2"ist fürAtoiungültig. Für Dezimalzahlen nimmParseFloat.- Bei einem Bereichsfehler gibt
ParseIntden größten passenden Wert (127fürint8) zusammen mit dem Fehler zurück. Verwende den Wert nicht, wenn der Fehler nicht nil ist. - Die Fehler sind
*strconv.NumError-Werte, diestrconv.ErrSyntaxoderstrconv.ErrRangewrappen, also kannerrors.Issie unterscheiden.
ParseBool akzeptiert 1, t, T, TRUE, true, True und die entsprechenden Formen für false. "yes" und "on" sind Fehler.
Die Falle string(65)
Eine Ganzzahl in string zu konvertieren erzeugt keine Ziffern. Es erzeugt das Zeichen mit diesem Unicode-Codepoint:
n := 65
s := string(n) // "A", not "65"
Der Compiler akzeptiert das, aber go vet meldet es:
./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits
Willst du wirklich das Zeichen, sag es mit einer Rune: string(rune(n)). Willst du die Zahl als Text, nimm strconv.Itoa(n). Eine rune oder ein byte in string zu konvertieren ist in Ordnung und verbreitet:
Strings, Bytes und Runes
string, []byte und []rune lassen sich mit T(v) ineinander konvertieren. Jede Konvertierung kopiert die Daten, weil Strings unveränderlich sind und Slices nicht:
Konvertiere in []rune, wenn du zeichenweise indizieren oder ändern musst; konvertiere in []byte für I/O, Hashing und Änderungen auf Byte-Ebene. Die Seite zu Runes und Bytes erklärt UTF-8 im Detail.
Konvertierung vs Type Assertion
Eine Konvertierung macht aus einem Wert eines konkreten Typs einen anderen. Den konkreten Wert aus einem Interface (any, error, io.Reader) zu holen ist eine andere Operation, die Type Assertion:
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
Erst die Assertion, dann die Konvertierung. Die Comma-ok-Form n, ok := v.(int) vermeidet eine Panic, wenn der Typ falsch ist.
Kurzreferenz
| Aufgabe | Code |
|---|---|
| int zu string | strconv.Itoa(n) |
| int64 zu string | strconv.FormatInt(n, 10) |
| string zu int | n, err := strconv.Atoi(s) |
| string zu int64 | n, err := strconv.ParseInt(s, 10, 64) |
| string zu float64 | f, err := strconv.ParseFloat(s, 64) |
| float64 zu string | strconv.FormatFloat(f, 'f', -1, 64) |
| float64 zu int | int(f) (schneidet ab) oder int(math.Round(f)) |
| int zu float64 | float64(n) |
| string zu []byte | []byte(s) |
| []byte zu string | string(b) |
| rune zu string | string(r) |
| bool zu string | strconv.FormatBool(b) |
| beliebiger Wert zu string | fmt.Sprint(v) |
Häufig gestellte Fragen
Wie konvertiere ich in Go ein int in einen String?
Mit strconv.Itoa(n): strconv.Itoa(42) gibt "42" zurück. Für ein int64 nimm strconv.FormatInt(n, 10). fmt.Sprint(n) funktioniert auch, für jeden Typ, ist aber langsamer. Schreib nicht string(n): Das behandelt n als Unicode-Codepoint, also ist string(65) gleich "A".
Wie konvertiere ich in Go einen String in ein int?
Mit strconv.Atoi, das die Zahl und einen Fehler zurückgibt:
n, err := strconv.Atoi("42")
if err != nil {
// not a valid integer
}
Für eine bestimmte Größe oder Basis nimm strconv.ParseInt(s, 10, 64), das ein int64 zurückgibt. Atoi entfernt keine Leerzeichen, also ist " 42" ein Fehler; ruf vorher strings.TrimSpace auf.
Wie castet man in Go?
Go nennt es Konvertierung, und die Syntax ist T(v): float64(n), int(f), []byte(s). Sie funktioniert zwischen numerischen Typen, zwischen Strings und Byte- oder Rune-Slices und zwischen Typen mit demselben zugrunde liegenden Typ. Text parst sie nicht: Um aus "42" eine 42 zu machen, brauchst du strconv. Einen konkreten Typ aus einem Interface zu holen ist eine Type Assertion, v.(T), keine Konvertierung.
Wie konvertiere ich in Go einen Float in ein int?
int(f) schneidet in Richtung null ab: int(3.9) ist 3 und int(-3.9) ist -3. Zum Runden nimm int(math.Round(f)). Liegt der Float außerhalb des Bereichs des Ganzzahltyps, ist das Ergebnis implementierungsabhängig, also prüf den Bereich vorher, wenn der Wert aus einer Eingabe stammt.
Warum gibt string(65) in Go „A“ zurück?
Die Konvertierung einer Ganzzahl in string interpretiert sie als Unicode-Codepoint, und 65 ist der Codepoint von A. go vet meldet das: conversion from int to string yields a string of one rune, not a string of digits. Nimm strconv.Itoa(65), um "65" zu bekommen.