Lompati ke konten utama
Modul 6 · Pelajaran 4 dari 529/50 dalam kursus~10 min
Pelajaran modul (4/5)

Antarmuka Stringer

fmt.Stringer mungkin adalah antarmuka standar yang paling banyak digunakan Perpustakaan standar Go. Ini adalah demonstrasi kekuatan yang sempurna antarmuka kecil.

Definisi

Go
type Stringer interface {
    String() string
}

Satu tanda tangan. Jenis apa pun yang mendefinisikan String() string memenuhi itu. Dan fmt mengenali antarmuka ini: saat Anda memberikan nilai ke fmt.Print*, jika mengimplementasikan Stringer maka hasil String() digunakan sebagai pengganti representasi default.

Contoh

Go
type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}

fmt.Println(Point{1, 2})              // (1,2)
fmt.Printf("%v %s\n", Point{3, 4}, Point{5, 6})
// (3,4) (5,6)

Nilai yang sama dicetak dengan format khusus di %v, %s, Println, Sprint, log, dll. Semua hanya dengan mendefinisikan satu metode.

Ketika itu masuk akal

  • Jenis yang memodelkan domain (id, kode, koordinat, enumerasi).
  • Kesalahan dengan representasi yang dapat dibaca manusia (lihat pelajaran selanjutnya di error).
  • Jenis yang sering Anda log dan ingin formatnya tetap.

Tidak untuk semuanya: jika tipenya sederhana dan representasi default baik-baik saja, jangan menambah kebisingan.

Jenis enum: pola umum dengan iota

Go
type Status int

const (
    OK Status = iota
    WARN
    ERR
)

func (s Status) String() string {
    switch s {
    case OK:   return "OK"
    case WARN: return "WARN"
    case ERR:  return "ERR"
    default:   return "UNKNOWN"
    }
}

fmt.Println(OK, WARN, ERR)   // OK WARN ERR

Tanpa String(), fmt.Println(OK) akan mencetak 0. Dengan String(), itu mencetak nama simbolis. stringer alat menghasilkan pola ini secara otomatis.

Hati-hati dengan rekursi tanpa batas

Go
type T int
func (t T) String() string {
    return fmt.Sprintf("%d", int(t))  // OK: cast to int breaks the recursion
}

Stringer pada penerima penunjuk

Jika String() memiliki penerima penunjuk, hanya *T yang memenuhi Stringer. Dengan fmt.Println(t) (sebuah nilai), Go melihat kumpulan metode T, tidak menemukannya, dan menggunakan format default. Untuk menghindari hal ini, nilai receiver biasanya digunakan untuk String() (ini adalah "tampilan"; tidak memodifikasi apa pun).

Cobalah

Latihan#go.m6.l4.e1
Upaya: 0Memuat…

Implementasikan String() pada Point sehingga mengembalikan (X,Y).

Memuat editor…
Tunjukkan petunjuk

Gunakan `fmt.Sprintf` untuk memformat bidang.

Solusi tersedia setelah 3 upaya

Latihan#go.m6.l4.e2
Upaya: 0Memuat…

Implementasikan String() pada tipe Status (int): 0 → 'OK', 1 → 'WARN', jika tidak → 'ERR'.

Memuat editor…
Tunjukkan petunjuk

Aktifkan nilai penerima; ingat untuk memberikan default.

Solusi tersedia setelah 3 upaya

Quiz#go.m6.l4.e3
Siap

Tanda tangan manakah yang harus dimiliki metode tersebut untuk memenuhi fmt.Stringer?

Go
func (x T) ??? {}
Pilihan jawaban

Rekap

  • fmt.Stringer = interface { String() string }.
  • Menerapkannya mengubah cara fmt.Print* merepresentasikan tipe.
  • Idiomatik untuk enum (iota), tipe domain, kode/pengidentifikasi.
  • Jangan pernah menelepon fmt.Sprintf("%s", t) di t di dalam String() (rekursi).
  • Konvensi: penerima nilai untuk String() (tidak ada mutasi, menghindari "kejutan set metode").