Menu

Int na string, string na int i konwersja typów w Golang

Jak konwertować typy w Go: int na string i string na int przez strconv, liczby zmiennoprzecinkowe na całkowite, konwersje liczbowe przez T(v), bajty i rune, pułapka string(65) i obsługa błędów konwersji.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Go nigdy nie konwertuje typów niejawnie. Między zgodnymi typami konwertujesz przez T(v), a między liczbami i tekstem przez pakiet strconv. Dwie najczęściej wyszukiwane konwersje:

strconv.Itoa („integer to ASCII”) formatuje int jako tekst dziesiętny. strconv.Atoi („ASCII to integer”) parsuje tekst na int i zwraca błąd, gdy tekst nie jest poprawną liczbą. Zawsze sprawdzaj ten błąd.

Konwersja T(v)

Składnia konwersji w Go wygląda jak wywołanie funkcji nazwanej tak jak typ docelowy. Działa w trzech sytuacjach:

  1. między typami liczbowymi (int, int64, float64, uint8, ...),
  2. między string a []byte lub []rune,
  3. między typami, które mają wspólny typ bazowy (Celsius i float64).

Przyjrzyj się wynikom:

  • int(3.9) to 3, a int(-3.9) to -3. Konwersja obcina w stronę zera; nie zaokrągla. Aby wybrać zachowanie, najpierw użyj math.Round, math.Floor lub math.Ceil. math.Round zaokrągla połówki od zera, więc -3.5 staje się -4.
  • uint8(300) to 44, bo zostaje tylko 8 najmłodszych bitów (300 minus 256), a int8(200) to -56 z tego samego powodu. Bez błędu i bez panic.
  • Celsius i float64 mają wspólny typ bazowy, więc konwertują się swobodnie, ale tylko jawnie.

Wartości są celowo w zmiennych. Ze stałymi te same konwersje się nie kompilują.

Stałe są sprawdzane, zmienne nie

Konwersja stałej, która się nie mieści, to błąd kompilacji. Konwersja zmiennej o tej samej wartości po cichu zawija wartość:

fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8

Konwersja stałej niecałkowitej na typ całkowity też jest odrzucana, a ta sama wartość w zmiennej jest obcinana:

./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int

Jeśli liczba zmiennoprzecinkowa jest poza zakresem docelowego typu całkowitego (na przykład int64(1e20)), wynik zależy od implementacji: na przykład amd64 i arm64 dają różne odpowiedzi. Sprawdzaj zakres przed konwersją niezaufanych wartości.

Konwersja liczb na stringi

ZFunkcjaPrzykładWynik
intstrconv.Itoa(n)strconv.Itoa(-7)"-7"
int64strconv.FormatInt(n, base)strconv.FormatInt(255, 16)"ff"
uint64strconv.FormatUint(n, base)strconv.FormatUint(5, 2)"101"
float64strconv.FormatFloat(f, fmt, prec, 64)strconv.FormatFloat(3.14159, 'f', 2, 64)"3.14"
boolstrconv.FormatBool(b)strconv.FormatBool(true)"true"
cokolwiekfmt.Sprint(v)fmt.Sprint(3.5)"3.5"
cokolwiek, sformatowanefmt.Sprintf(format, v)fmt.Sprintf("%05d", 42)"00042"

FormatFloat przyjmuje bajt formatu ('f' dla stałego przecinka, 'e' dla wykładnika, 'g' dla krótszej z tych form), precyzję (-1 oznacza „najmniej cyfr, które pozwalają dokładnie odtworzyć wartość”) i rozmiar w bitach oryginalnej liczby (64 lub 32).

strconv jest szybszy niż fmt.Sprint, który opakowuje wartość w interfejs i przechodzi przez ogólną ścieżkę formatowania fmt. W gorącej pętli ta różnica jest widoczna; przy sporadycznych konwersjach wybierz to, co czyta się lepiej.

Konwersja stringów na liczby

NaFunkcjaZwraca
intstrconv.Atoi(s)int, error
dowolny int ze znakiemstrconv.ParseInt(s, base, bitSize)int64, error
dowolny int bez znakustrconv.ParseUint(s, base, bitSize)uint64, error
floatstrconv.ParseFloat(s, bitSize)float64, error
boolstrconv.ParseBool(s)bool, error

ParseInt zawsze zwraca int64. Argument bitSize (0, 8, 16, 32, 64) ustala akceptowany zakres, więc wynik na pewno się zmieści, gdy przekonwertujesz go na mniejszy typ. base 0 oznacza „wywnioskuj z prefiksu”, więc 0x1f, 0o17, 0b101 i 1_000 są parsowane.

Co pokazuje wynik:

  • " 42" się nie parsuje. Atoi akceptuje opcjonalny znak i cyfry, nic więcej. Dane z bufio zwykle kończą się na \n, więc je przytnij.
  • "4.2" jest niepoprawne dla Atoi. Do liczb dziesiętnych użyj ParseFloat.
  • Przy błędzie przekroczenia zakresu ParseInt zwraca największą wartość, która się mieści (127 dla int8), razem z błędem. Nie używaj tej wartości, gdy błąd nie jest nil.
  • Błędy to wartości *strconv.NumError opakowujące strconv.ErrSyntax lub strconv.ErrRange, więc errors.Is potrafi je odróżnić.

ParseBool akceptuje 1, t, T, TRUE, true, True i odpowiadające im formy dla fałszu. "yes" i "on" to błędy.

Pułapka string(65)

Konwersja liczby całkowitej na string nie daje cyfr. Daje znak o tym punkcie kodowym Unicode:

n := 65
s := string(n) // "A", not "65"

Kompilator to akceptuje, ale go vet to zgłasza:

./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits

Jeśli naprawdę chcesz znak, powiedz to wprost przez runę: string(rune(n)). Jeśli chcesz liczbę jako tekst, użyj strconv.Itoa(n). Konwersja rune lub byte na string jest poprawna i częsta:

Stringi, bajty i rune

string, []byte i []rune konwertują się między sobą przez T(v). Każda konwersja kopiuje dane, bo stringi są niezmienne, a slice'y nie:

Konwertuj na []rune, gdy musisz indeksować lub modyfikować po znakach; konwertuj na []byte do wejścia i wyjścia, hashowania i edycji na poziomie bajtów. Strona o runach i bajtach szczegółowo omawia UTF-8.

Konwersja a asercja typu

Konwersja zmienia wartość z jednego typu konkretnego na inny. Wydobycie konkretnej wartości z interfejsu (any, error, io.Reader) to inna operacja, asercja typu:

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

Najpierw asercja, potem konwersja. Forma comma-ok n, ok := v.(int) pozwala uniknąć panic, gdy typ jest zły.

Ściągawka

ZadanieKod
int na stringstrconv.Itoa(n)
int64 na stringstrconv.FormatInt(n, 10)
string na intn, err := strconv.Atoi(s)
string na int64n, err := strconv.ParseInt(s, 10, 64)
string na float64f, err := strconv.ParseFloat(s, 64)
float64 na stringstrconv.FormatFloat(f, 'f', -1, 64)
float64 na intint(f) (obcina) lub int(math.Round(f))
int na float64float64(n)
string na []byte[]byte(s)
[]byte na stringstring(b)
rune na stringstring(r)
bool na stringstrconv.FormatBool(b)
dowolna wartość na stringfmt.Sprint(v)

Najczęściej zadawane pytania

Jak zamienić int na string w Go?

Użyj strconv.Itoa(n): strconv.Itoa(42) zwraca "42". Dla int64 użyj strconv.FormatInt(n, 10). fmt.Sprint(n) też działa dla każdego typu, ale jest wolniejsze. Nie pisz string(n): to traktuje n jako punkt kodowy Unicode, więc string(65) to "A".

Jak zamienić string na int w Go?

Użyj strconv.Atoi, która zwraca liczbę i błąd:

n, err := strconv.Atoi("42")
if err != nil {
	// not a valid integer
}

Dla konkretnego rozmiaru lub podstawy użyj strconv.ParseInt(s, 10, 64), która zwraca int64. Atoi nie usuwa spacji, więc " 42" daje błąd; najpierw wywołaj strings.TrimSpace.

Jak zrobić rzutowanie (cast) w Go?

Go nazywa to konwersją, a składnia to T(v): float64(n), int(f), []byte(s). Działa między typami liczbowymi, między stringami a slice'ami bajtów lub run oraz między typami o tym samym typie bazowym. Nie parsuje tekstu: zamiana "42" na 42 wymaga strconv. Wydobycie konkretnego typu z interfejsu to asercja typu, v.(T), a nie konwersja.

Jak zamienić float na int w Go?

int(f) obcina w stronę zera: int(3.9) to 3, a int(-3.9) to -3. Aby zaokrąglić, użyj int(math.Round(f)). Jeśli liczba zmiennoprzecinkowa jest poza zakresem typu całkowitego, wynik zależy od implementacji, więc gdy wartość pochodzi z wejścia, najpierw sprawdź zakres.

Dlaczego string(65) zwraca "A" w Go?

Konwersja liczby całkowitej na string interpretuje ją jako punkt kodowy Unicode, a 65 to punkt kodowy A. go vet to zgłasza: conversion from int to string yields a string of one rune, not a string of digits. Użyj strconv.Itoa(65), aby dostać "65".

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ