Go tidak pernah mengonversi tipe secara implisit. Kamu mengonversi antartipe yang kompatibel dengan T(v), dan antara angka dan teks dengan package strconv. Dua konversi yang paling sering dicari:
strconv.Itoa ("integer to ASCII") memformat int sebagai teks desimal. strconv.Atoi ("ASCII to integer") melakukan parse pada teks menjadi int dan mengembalikan error kalau teksnya bukan angka yang valid. Selalu periksa error itu.
Konversi T(v)
Sintaks konversi Go terlihat seperti pemanggilan fungsi yang dinamai sesuai tipe tujuan. Konversi ini bekerja dalam tiga situasi:
- antartipe angka (
int,int64,float64,uint8, ...), - antara
stringdan[]byteatau[]rune, - antartipe yang punya underlying type yang sama (
Celsiusdanfloat64).
Baca hasilnya dengan teliti:
int(3.9)bernilai3danint(-3.9)bernilai-3. Konversi memotong ke arah nol; konversi tidak membulatkan. Pakaimath.Round,math.Floor, ataumath.Ceillebih dulu untuk memilih perilakunya.math.Roundmembulatkan setengah menjauhi nol, jadi-3.5menjadi-4.uint8(300)bernilai44, karena hanya 8 bit terbawah yang tersisa (300 dikurangi 256), danint8(200)bernilai-56karena alasan yang sama. Tidak ada error, tidak ada panic.Celsiusdanfloat64punya underlying type yang sama, jadi keduanya bisa dikonversi dengan bebas, tetapi hanya secara eksplisit.
Nilai-nilainya sengaja disimpan di variabel. Dengan konstanta, konversi yang sama tidak bisa dikompilasi.
Konstanta diperiksa, variabel tidak
Mengonversi konstanta yang tidak muat adalah error kompilasi. Mengonversi variabel dengan nilai yang sama akan wrap tanpa peringatan:
fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8
Mengonversi konstanta bukan bilangan bulat ke tipe integer juga ditolak, sementara nilai yang sama di dalam variabel akan dipotong:
./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int
Kalau nilai float berada di luar jangkauan tipe integer tujuan (misalnya int64(1e20)), hasilnya bergantung pada implementasi: amd64 dan arm64, misalnya, memberi jawaban yang berbeda. Periksa jangkauannya sebelum mengonversi nilai yang tidak tepercaya.
Mengonversi angka ke string
| Dari | Fungsi | Contoh | Hasil |
|---|---|---|---|
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" |
| apa saja | fmt.Sprint(v) | fmt.Sprint(3.5) | "3.5" |
| apa saja, diformat | fmt.Sprintf(format, v) | fmt.Sprintf("%05d", 42) | "00042" |
FormatFloat menerima byte format ('f' untuk fixed, 'e' untuk eksponen, 'g' untuk mana pun yang lebih pendek), presisi (-1 berarti "digit paling sedikit yang tetap kembali ke nilai yang persis sama"), dan ukuran bit float aslinya (64 atau 32).
strconv lebih cepat daripada fmt.Sprint, yang membungkus nilainya dalam interface dan melewati jalur format umum milik fmt. Di perulangan yang sangat sering dijalankan, perbedaan itu terasa; untuk konversi yang sesekali, pilih mana yang lebih enak dibaca.
Mengonversi string ke angka
| Ke | Fungsi | Mengembalikan |
|---|---|---|
int | strconv.Atoi(s) | int, error |
| int bertanda apa pun | strconv.ParseInt(s, base, bitSize) | int64, error |
| int tak bertanda apa pun | strconv.ParseUint(s, base, bitSize) | uint64, error |
| float | strconv.ParseFloat(s, bitSize) | float64, error |
| bool | strconv.ParseBool(s) | bool, error |
ParseInt selalu mengembalikan int64. Argumen bitSize (0, 8, 16, 32, 64) menentukan jangkauan yang diterima, jadi hasilnya dijamin muat saat kamu mengonversinya ke tipe yang lebih kecil. base 0 berarti "tebak dari prefix-nya", jadi 0x1f, 0o17, 0b101, dan 1_000 semuanya bisa dibaca.
Hal yang ditunjukkan output-nya:
" 42"gagal.Atoimenerima tanda opsional dan digit, tidak lebih. Input daribufiobiasanya diakhiri\n, jadi pangkas dulu."4.2"tidak valid untukAtoi. PakaiParseFloatuntuk bilangan desimal.- Pada error di luar jangkauan,
ParseIntmengembalikan nilai terbesar yang muat (127untukint8) bersama error-nya. Jangan pakai nilainya kalau error-nya bukan nil. - Error-nya berupa nilai
*strconv.NumErroryang membungkusstrconv.ErrSyntaxataustrconv.ErrRange, jadierrors.Isbisa membedakannya.
ParseBool menerima 1, t, T, TRUE, true, True, dan bentuk false yang sepadan. "yes" dan "on" menghasilkan error.
Jebakan string(65)
Mengonversi integer ke string tidak menghasilkan digit. Hasilnya adalah karakter dengan code point Unicode tersebut:
n := 65
s := string(n) // "A", not "65"
Compiler menerimanya, tetapi go vet melaporkannya:
./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits
Kalau kamu memang menginginkan karakternya, tulis dengan jelas memakai rune: string(rune(n)). Kalau kamu ingin angkanya sebagai teks, pakai strconv.Itoa(n). Mengonversi rune atau byte ke string tidak masalah dan umum dilakukan:
String, byte, dan rune
string, []byte, dan []rune bisa saling dikonversi dengan T(v). Setiap konversi menyalin datanya, karena string bersifat immutable sedangkan slice tidak:
Konversikan ke []rune kalau kamu perlu mengakses indeks atau mengubah isi per karakter; konversikan ke []byte untuk I/O, hashing, dan perubahan di level byte. Halaman rune dan byte membahas UTF-8 secara detail.
Konversi vs type assertion
Konversi mengubah nilai dari satu tipe konkret ke tipe konkret lain. Mengambil nilai konkret dari sebuah interface (any, error, io.Reader) adalah operasi yang berbeda, yaitu 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
Lakukan assertion lebih dulu, baru konversi. Bentuk comma-ok n, ok := v.(int) mencegah panic kalau tipenya salah.
Referensi singkat
| Tugas | Kode |
|---|---|
| int ke string | strconv.Itoa(n) |
| int64 ke string | strconv.FormatInt(n, 10) |
| string ke int | n, err := strconv.Atoi(s) |
| string ke int64 | n, err := strconv.ParseInt(s, 10, 64) |
| string ke float64 | f, err := strconv.ParseFloat(s, 64) |
| float64 ke string | strconv.FormatFloat(f, 'f', -1, 64) |
| float64 ke int | int(f) (dipotong) atau int(math.Round(f)) |
| int ke float64 | float64(n) |
| string ke []byte | []byte(s) |
| []byte ke string | string(b) |
| rune ke string | string(r) |
| bool ke string | strconv.FormatBool(b) |
| nilai apa pun ke string | fmt.Sprint(v) |
Pertanyaan yang sering diajukan
Bagaimana cara mengonversi int ke string di Go?
Pakai strconv.Itoa(n): strconv.Itoa(42) mengembalikan "42". Untuk int64, pakai strconv.FormatInt(n, 10). fmt.Sprint(n) juga bisa dipakai untuk tipe apa pun, tetapi lebih lambat. Jangan menulis string(n): cara itu memperlakukan n sebagai code point Unicode, jadi string(65) menghasilkan "A".
Bagaimana cara mengonversi string ke int di Go?
Pakai strconv.Atoi, yang mengembalikan angka dan sebuah error:
n, err := strconv.Atoi("42")
if err != nil {
// not a valid integer
}
Untuk ukuran atau basis tertentu, pakai strconv.ParseInt(s, 10, 64), yang mengembalikan int64. Atoi tidak memangkas spasi, jadi " 42" menghasilkan error; panggil strings.TrimSpace lebih dulu.
Bagaimana cara melakukan cast di Go?
Go menyebutnya konversi, dan sintaksnya T(v): float64(n), int(f), []byte(s). Konversi bisa dilakukan antartipe angka, antara string dan slice byte atau rune, dan antartipe yang punya underlying type yang sama. Konversi tidak melakukan parse pada teks: mengubah "42" menjadi 42 butuh strconv. Mengambil tipe konkret dari sebuah interface adalah type assertion, v.(T), bukan konversi.
Bagaimana cara mengonversi float ke int di Go?
int(f) memotong ke arah nol: int(3.9) bernilai 3 dan int(-3.9) bernilai -3. Untuk membulatkan, pakai int(math.Round(f)). Kalau float-nya di luar jangkauan tipe integer, hasilnya bergantung pada implementasi, jadi periksa jangkauannya lebih dulu kalau nilainya berasal dari input.
Kenapa string(65) mengembalikan "A" di Go?
Mengonversi integer ke string menafsirkannya sebagai code point Unicode, dan 65 adalah code point dari A. go vet menandainya: conversion from int to string yields a string of one rune, not a string of digits. Pakai strconv.Itoa(65) untuk mendapatkan "65".