Package fmt punya tiga keluarga fungsi cetak, dan setiap keluarga punya tiga varian yang sama:
| Fungsi | Output dikirim ke | Format |
|---|---|---|
Print, Println, Printf | standard output | default, default dengan spasi dan baris baru, string format |
Sprint, Sprintln, Sprintf | string yang dikembalikan | tiga gaya yang sama |
Fprint, Fprintln, Fprintf | io.Writer apa pun (file, buffer, respons HTTP) | tiga gaya yang sama |
Errorf | error yang dikembalikan | string format, ditambah %w untuk membungkus |
Println menambahkan spasi di antara operand dan baris baru di akhir. Printf tidak menambahkan apa-apa: kamu sendiri yang menulis \n. Print menambahkan spasi hanya di antara operand yang keduanya bukan string, dan itu cukup mengejutkan sehingga kebanyakan kode memakai Println atau Printf.
Format Verb
Umum
| Verb | Mencetak | Contoh output |
|---|---|---|
%v | nilai dalam format default | {Ana 31 [admin]} |
%+v | struct beserta nama field-nya | {Name:Ana Age:31 Tags:[admin]} |
%#v | sintaks Go untuk nilai tersebut | main.User{Name:"Ana", Age:31, Tags:[]string{"admin"}} |
%T | tipenya | main.User |
%% | tanda persen literal | % |
%+v adalah pilihan utama saat debugging. Pointer ke struct dicetak sebagai &{...}, bukan alamat. Map dicetak dengan key yang terurut, jadi output-nya stabil meskipun urutan iterasi map acak.
Integer
| Verb | Arti | fmt.Sprintf(verb, 255) |
|---|---|---|
%d | desimal | 255 |
%b | biner | 11111111 |
%o | oktal | 377 |
%O | oktal dengan prefiks 0o | 0o377 |
%x / %X | heksadesimal, huruf kecil atau besar | ff / FF |
%#x | heksadesimal dengan prefiks 0x | 0xff |
%c | karakter dengan code point tersebut | ÿ |
%q | literal karakter dalam tanda kutip | 'ÿ' |
%U | format Unicode | U+00FF |
Float
| Verb | Arti | fmt.Sprintf(verb, 1234.5678) |
|---|---|---|
%f | desimal, 6 angka di belakang koma secara default | 1234.567800 |
%.2f | desimal, 2 angka di belakang koma | 1234.57 |
%e | notasi ilmiah | 1.234568e+03 |
%g | %e atau %f, mana yang lebih pendek, tanpa nol di akhir | 1234.5678 |
%v | sama dengan %g | 1234.5678 |
%.2f membulatkan nilai biner eksak dari float itu, jadi fmt.Sprintf("%.2f", 2.675) menghasilkan 2.67: float64 terdekat dengan 2,675 sedikit lebih kecil dari angka itu. Jangan pernah memformat uang dari float; simpan sen dalam integer.
String dan byte
| Verb | Arti | fmt.Sprintf(verb, "go\n") |
|---|---|---|
%s | string apa adanya | go dan baris baru |
%q | dalam tanda kutip ganda, escape ditampilkan | "go\n" |
%x | heksadesimal dari setiap byte | 676f0a |
% x | heksadesimal dengan spasi | 67 6f 0a |
%s pada []byte mencetaknya sebagai teks; %v mencetak angka-angkanya ([104 105]).
Tipe lain
| Verb | Tipe | Mencetak |
|---|---|---|
%t | bool | true atau false |
%p | pointer, slice, map, channel, func | alamatnya, seperti 0xc000012345 |
%w | error (hanya di Errorf) | pesan error-nya, sekaligus membungkusnya |
Width, Presisi, dan Padding
Di antara % dan verb, kamu bisa menaruh flag, width, dan presisi:
| Bentuk | Efek |
|---|---|
%5d | width 5, rata kanan (diisi spasi di kiri) |
%-5d | width 5, rata kiri |
%05d | diisi dengan nol |
%.2f | 2 digit di belakang titik desimal |
%8.2f | width 8 dan 2 angka desimal |
%.3s | paling banyak 3 karakter dari string |
%+d | selalu tampilkan tanda |
%*d | width diambil dari argumen berikutnya |
Perhatikan bahwa %.0f dari 2.5 mencetak 2: di sini Go membulatkan setengah ke angka genap. Width menghitung rune untuk string, bukan kolom tampilan, jadi karakter CJK dan emoji masih bisa membuat tabel tidak rata. Untuk kolom teks dengan panjang yang berbeda-beda, text/tabwriter melakukan pengukurannya untukmu.
Indeks argumen
%[n] memilih argumen berdasarkan posisinya, sehingga kamu bisa memakai satu argumen berulang kali:
fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10) // 10 a 1010
Errorf dan %w
fmt.Errorf membuat error dari string format. Dengan %w, fungsi ini juga membungkus error lain, sehingga pemanggil masih bisa mendeteksi error aslinya:
Pakai %w saat pemanggil mungkin perlu memeriksa penyebabnya, dan %v saat kamu sengaja menyembunyikannya. Sejak Go 1.20, satu pemanggilan Errorf boleh berisi beberapa verb %w. Halaman penanganan error membahas wrapping secara mendalam.
Format Kustom dengan String()
Tipe apa pun yang punya method String() string mengatur cara %v, %s, dan Println menampilkannya:
%d melewati String() dan mencetak angka di baliknya. Untuk tipe error, method yang setara adalah Error() string, yang lebih diutamakan daripada String().
Saat Verb-nya Salah
fmt tidak pernah panic karena format yang salah. Ia mencetak masalahnya di tempat:
fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)
Output seperti itu cenderung lolos sampai ke produksi karena tidak membuat apa pun crash. go vet menangkap ketiganya saat build:
./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args
Catatan Performa
fmt menerima setiap argumen sebagai any dan memeriksa tipenya saat program berjalan (memakai reflection untuk struct, slice, dan map), dan itu tidak masalah untuk logging dan output, tetapi terasa di loop yang ketat. Untuk mengonversi satu angka, strconv.Itoa dan strconv.FormatFloat lebih cepat dari Sprintf. Untuk membangun string panjang di dalam loop, tulis ke strings.Builder dengan fmt.Fprintf(&b, ...) alih-alih menyambung hasil-hasil Sprintf.
Pertanyaan yang sering diajukan
Apa bedanya Println, Printf, dan Sprintf di Go?
fmt.Println mencetak argumennya dengan dipisahkan spasi dan baris baru di akhir. fmt.Printf mencetak sesuai string format dan tidak menambahkan baris baru. fmt.Sprintf memformat dengan cara yang sama seperti Printf, tetapi mengembalikan hasilnya sebagai string alih-alih mencetaknya. fmt.Errorf melakukan hal yang sama dan mengembalikan error.
Bagaimana cara mencetak struct beserta nama field-nya di Go?
Pakai %+v: fmt.Printf("%+v\n", user) mencetak {Name:Ana Age:31}. %v hanya mencetak nilainya, {Ana 31}, dan %#v mencetak sintaks Go termasuk tipenya, main.User{Name:"Ana", Age:31}.
Bagaimana cara memformat float menjadi 2 angka di belakang koma di Go?
Pakai %.2f: fmt.Sprintf("%.2f", 3.14159) mengembalikan "3.14". Tambahkan width untuk meratakan kolom, %8.2f, atau tanda minus untuk rata kiri, %-8.2f. strconv.FormatFloat(f, 'f', 2, 64) memberi hasil yang sama tanpa string format.
Apa fungsi %w di fmt.Errorf?
%w memformat error seperti %v sekaligus membungkusnya, jadi error yang baru membawa error aslinya. errors.Is dan errors.As lalu bisa menemukan error yang dibungkus itu: err := fmt.Errorf("load config: %w", os.ErrNotExist) membuat errors.Is(err, os.ErrNotExist) bernilai true. %w hanya berfungsi di fmt.Errorf.
Kenapa output saya menampilkan %!d(string=...)?
Verb-nya tidak cocok dengan tipe argumennya, misalnya %d yang diberi string. fmt mencetak masalahnya di tempat alih-alih panic: %!d(string=oops). Argumen yang kurang mencetak %!d(MISSING) dan yang berlebih mencetak %!(EXTRA int=2). go vet menangkap ketiganya sebelum kamu menjalankan program.