Hampir semua program Go menyentuh package fmt: menampilkan hasil, menyusun teks terformat, membaca masukan, sampai membungkus pesan error. Chapter fmt.Println
telah memperkenalkan fungsi cetak dasarnya; chapter ini membedah sisanya: tabel verb lengkap, lebar dan presisi kolom, keluarga Sprint, interface Stringer, verb %w, dan fmt.Scan. Seluruh contoh dijalankan sungguhan sehingga setiap verb dapat dibandingkan dengan hasil aslinya.
Tiga Keluarga Fungsi #
Package fmt menyusun fungsinya dalam tiga keluarga. Setiap keluarga punya tiga variasi: bentuk polos, akhiran ln yang menambah spasi antar argumen lalu baris baru, dan akhiran f yang memakai pola format. Tabel berikut merangkum ketiganya:
| Keluarga | Fungsi | Tujuan |
|---|---|---|
| Cetak | Print, Println, Printf | Menulis ke standard output (layar) |
| String | Sprint, Sprintln, Sprintf | Mengembalikan string tanpa mencetak |
| Tulis | Fprint, Fprintln, Fprintf | Menulis ke io.Writer mana pun, misalnya os.Stdout atau berkas |
Keluarga Sprint dipakai saat teks terformat dibutuhkan sebagai nilai, misalnya isi field struct atau pesan log. Keluarga Fprint menulis ke io.Writer mana pun dan muncul lagi pada chapter io dan utilitasnya
.
Tabel Verb Format #
Verb adalah penanda tempat pada pola format yang diganti nilai argumen, misalnya %d untuk bilangan bulat. Berikut verb yang paling sering dipakai beserta contoh hasilnya:
| Verb | Kegunaan | Contoh hasil |
|---|---|---|
%v | format default untuk tipe apa pun | {Kopi Gayo 25000} |
%+v | seperti %v, plus nama field struct | {Nama:Kopi Gayo Harga:25000} |
%#v | representasi sintaks Go | main.Produk{Nama:"Kopi Gayo", Harga:25000} |
%T | tipe dari nilai | main.Produk |
%d | bilangan bulat basis sepuluh | 255 |
%s | teks string mentah | Go |
%q | string dengan tanda kutip | "Go" |
%x | heksadesimal: bilangan atau isi byte string | ff, 476f |
%f | desimal dengan enam angka di belakang koma | 3.140000 |
%g | desimal paling ringkas | 3.14 |
%e | notasi ilmiah | 3.140000e+00 |
%t | nilai boolean | true |
%p | alamat pointer, misalnya 0xc0000123456 | berbeda tiap eksekusi |
Program Utuh #
Berkas fmt-demo.go mempraktikkan semua materi di atas dalam satu program:
package main
import (
"errors"
"fmt"
"os"
)
// Produk tidak memiliki method String,
// sehingga fmt memakai format bawaan untuk struct.
type Produk struct {
Nama string
Harga int
}
// Siswa mengimplementasikan interface fmt.Stringer.
type Siswa struct {
Nama string
Umur int
}
// String membuat fmt memakai teks ini alih-alih format struct bawaan.
func (s Siswa) String() string {
return fmt.Sprintf("siswa %s (%d tahun)", s.Nama, s.Umur)
}
func main() {
// Keluarga Sprint menghasilkan string tanpa mencetak apa pun.
sapaan := fmt.Sprint("Harga kopi: ", 25000)
barisan := fmt.Sprintln("Stok kopi:", 12)
ringkas := fmt.Sprintf("%s punya %d gram", "Budi", 250)
fmt.Println(sapaan)
fmt.Printf("sprintln: %q\n", barisan)
fmt.Println(ringkas)
// Verb untuk struct tanpa method String.
kopi := Produk{Nama: "Kopi Gayo", Harga: 25000}
fmt.Printf("%%v : %v\n", kopi)
fmt.Printf("%%+v : %+v\n", kopi)
fmt.Printf("%%#v : %#v\n", kopi)
fmt.Printf("%%T : %T\n", kopi)
// Verb untuk nilai dasar.
fmt.Printf("%%d : %d %%x : %x\n", 255, 255)
fmt.Printf("%%s : %s %%q : %q\n", "Go", "Go")
fmt.Printf("%%x : %x (string)\n", "Go")
fmt.Printf("%%f : %f\n", 3.14)
fmt.Printf("%%g : %g %%e : %e\n", 3.14, 3.14)
fmt.Printf("%%t : %t\n", 255 > 100)
// Lebar dan presisi kolom.
fmt.Printf("[%%8.2f] : [%8.2f]\n", 1234.567)
fmt.Printf("[%%-10s] : [%-10s]\n", "Go")
fmt.Printf("[%%05d] : [%05d]\n", 42)
// Fprintf menulis ke io.Writer mana pun, bukan hanya layar.
fmt.Fprintf(os.Stdout, "fprintf ke os.Stdout: %s\n", "berhasil")
// Stringer dipanggil secara otomatis oleh fmt.
siti := Siswa{Nama: "Siti", Umur: 21}
fmt.Println(siti)
fmt.Printf("%v dan %s\n", siti, siti)
// Verb %w membungkus error agar tetap bisa diperiksa dengan errors.Is.
galat := errors.New("sambungan database gagal")
dibungkus := fmt.Errorf("ambil data: %w", galat)
fmt.Println(dibungkus)
fmt.Println("errors.Is:", errors.Is(dibungkus, galat))
}Jalankan program tersebut dari folder chapter:
go run fmt-demo.goOutput yang Dihasilkan:
Harga kopi: 25000
sprintln: "Stok kopi: 12\n"
Budi punya 250 gram
%v : {Kopi Gayo 25000}
%+v : {Nama:Kopi Gayo Harga:25000}
%#v : main.Produk{Nama:"Kopi Gayo", Harga:25000}
%T : main.Produk
%d : 255 %x : ff
%s : Go %q : "Go"
%x : 476f (string)
%f : 3.140000
%g : 3.14 %e : 3.140000e+00
%t : true
[%8.2f] : [ 1234.57]
[%-10s] : [Go ]
[%05d] : [00042]
fprintf ke os.Stdout: berhasil
siswa Siti (21 tahun)
siswa Siti (21 tahun) dan siswa Siti (21 tahun)
ambil data: sambungan database gagal
errors.Is: trueMari kita telaah baris demi baris program di atas:
- Baris 11-25:
Produktanpa methodStringmemakai format struct bawaan, sedangkanSiswamengimplementasikanfmt.Stringersehinggafmtmemakai teks kustomnya. - Baris 29-34: keluarga
Sprintmengembalikan string tanpa mencetak; tanda baris baru milikSprintlnterlihat saat isinya dicetak dengan%q. - Baris 38-49: membandingkan verb
%v,%+v,%#v,%T, lalu verb nilai dasar;%xpada string"Go"menghasilkan heksadesimal isi byte-nya,476f. - Baris 52-54:
%8.2fmengatur lebar 8 dengan dua angka di belakang koma,%-10smerata kiri, dan%05dmenambah nol di depan. - Baris 57-62:
Fprintfmenulis keio.Writermana pun (os.Stdout), danPrintln/Printfmemanggil methodString()miliksitisecara otomatis. - Baris 65-68: verb
%wmembungkus error asli sehinggaerrors.Istetap menemukannya.
Lebar dan Presisi Kolom #
Angka di antara persen dan verb mengatur tata letak kolom. Pola %8.2f berarti lebar minimum 8 karakter dengan 2 angka di belakang koma dan perataan kanan, sehingga 1234.567 menjadi 1234.57. Tanda minus pada %-10s meratakan ke kiri, sementara %05d mengisi ruang kosong dengan nol — cukup untuk laporan rapi di terminal.
Interface fmt.Stringer #
Interface Stringer adalah kontrak paling sederhana di fmt:
type Stringer interface {
String() string
}Ketika sebuah tipe memiliki method String() string, seluruh fungsi fmt memakai hasilnya untuk verb %v dan %s. Baris 61-62 membuktikannya: Siswa dicetak sebagai siswa Siti (21 tahun), bukan {Siti 21}.
Membungkus Error dengan %w #
Verb %w khusus dipakai di fmt.Errorf untuk membungkus error:
dibungkus := fmt.Errorf("ambil data: %w", galat)Membaca Input dengan fmt.Scan #
Selain mencetak, fmt membaca nilai dari standard input melalui Scan, Scanln, dan Scanf. Berkas fmt-scan-demo.go membaca satu string dan satu bilangan:
package main
import (
"fmt"
"os"
)
func main() {
var nama string
var umur int
// Scan membaca nilai yang dipisahkan spasi dari standard input.
n, err := fmt.Scan(&nama, &umur)
if err != nil {
fmt.Fprintln(os.Stderr, "input tidak lengkap:", err)
os.Exit(1)
}
fmt.Printf("terbaca %d nilai: %s berumur %d tahun\n", n, nama, umur)
}Program ini paling mudah diuji dengan mengirim teks lewat pipa:
echo "Budi 25" | go run fmt-scan-demo.goOutput yang Dihasilkan:
terbaca 2 nilai: Budi berumur 25 tahunMari kita telaah baris demi baris program di atas:
- Baris 9-10 (
var nama stringdanvar umur int): menyiapkan variabel penampung yang akan diisiScan. - Baris 13 (
n, err := fmt.Scan(&nama, &umur)): membaca dua token yang dipisahkan spasi atau baris baru; operator&mengirim alamat variabel agarScandapat mengisinya (lihat chapter Pointer dan Memory ). - Baris 14-17 (
if err != nil): menjaga program saat masukan tidak lengkap; tanpa input,Scanmengembalikan errorEOFdan program keluar dengan kode 1. - Baris 18: mencetak jumlah token yang terbaca beserta nilainya.
Scan cocok untuk input berbasis token seperti angka yang dipisah spasi. Untuk membaca baris penuh, chapter Package bufio
menyediakan Scanner yang lebih nyaman.
Referensi #
- Dokumentasi package fmt — fungsi, verb, dan aturan format.
- fmt.Printf — aturan pola format, lebar, dan presisi.
- fmt.Stringer
— definisi resmi interface
Stringer.
Dengan penguasaan fmt, output program Anda menjadi rapi dan galat tetap tertelusuri. Chapter berikutnya membahas package os: argumen command line, environment variable, dan kontrol keluar program.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
fmt-demo.go
Unduh berkaspackage main
import (
"errors"
"fmt"
"os"
)
// Produk tidak memiliki method String,
// sehingga fmt memakai format bawaan untuk struct.
type Produk struct {
Nama string
Harga int
}
// Siswa mengimplementasikan interface fmt.Stringer.
type Siswa struct {
Nama string
Umur int
}
// String membuat fmt memakai teks ini alih-alih format struct bawaan.
func (s Siswa) String() string {
return fmt.Sprintf("siswa %s (%d tahun)", s.Nama, s.Umur)
}
func main() {
// Keluarga Sprint menghasilkan string tanpa mencetak apa pun.
sapaan := fmt.Sprint("Harga kopi: ", 25000)
barisan := fmt.Sprintln("Stok kopi:", 12)
ringkas := fmt.Sprintf("%s punya %d gram", "Budi", 250)
fmt.Println(sapaan)
fmt.Printf("sprintln: %q\n", barisan)
fmt.Println(ringkas)
// Verb untuk struct tanpa method String.
kopi := Produk{Nama: "Kopi Gayo", Harga: 25000}
fmt.Printf("%%v : %v\n", kopi)
fmt.Printf("%%+v : %+v\n", kopi)
fmt.Printf("%%#v : %#v\n", kopi)
fmt.Printf("%%T : %T\n", kopi)
// Verb untuk nilai dasar.
fmt.Printf("%%d : %d %%x : %x\n", 255, 255)
fmt.Printf("%%s : %s %%q : %q\n", "Go", "Go")
fmt.Printf("%%x : %x (string)\n", "Go")
fmt.Printf("%%f : %f\n", 3.14)
fmt.Printf("%%g : %g %%e : %e\n", 3.14, 3.14)
fmt.Printf("%%t : %t\n", 255 > 100)
// Lebar dan presisi kolom.
fmt.Printf("[%%8.2f] : [%8.2f]\n", 1234.567)
fmt.Printf("[%%-10s] : [%-10s]\n", "Go")
fmt.Printf("[%%05d] : [%05d]\n", 42)
// Fprintf menulis ke io.Writer mana pun, bukan hanya layar.
fmt.Fprintf(os.Stdout, "fprintf ke os.Stdout: %s\n", "berhasil")
// Stringer dipanggil secara otomatis oleh fmt.
siti := Siswa{Nama: "Siti", Umur: 21}
fmt.Println(siti)
fmt.Printf("%v dan %s\n", siti, siti)
// Verb %w membungkus error agar tetap bisa diperiksa dengan errors.Is.
galat := errors.New("sambungan database gagal")
dibungkus := fmt.Errorf("ambil data: %w", galat)
fmt.Println(dibungkus)
fmt.Println("errors.Is:", errors.Is(dibungkus, galat))
}
fmt-scan-demo.go
Unduh berkaspackage main
import (
"fmt"
"os"
)
func main() {
var nama string
var umur int
// Scan membaca nilai yang dipisahkan spasi dari standard input.
n, err := fmt.Scan(&nama, &umur)
if err != nil {
fmt.Fprintln(os.Stderr, "input tidak lengkap:", err)
os.Exit(1)
}
fmt.Printf("terbaca %d nilai: %s berumur %d tahun\n", n, nama, umur)
}