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
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
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
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 ERRTanpa 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
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
Implementasikan String() pada Point sehingga mengembalikan (X,Y).
Tunjukkan petunjuk
Gunakan `fmt.Sprintf` untuk memformat bidang.
Solusi tersedia setelah 3 upaya
Implementasikan String() pada tipe Status (int): 0 → 'OK', 1 → 'WARN', jika tidak → 'ERR'.
Tunjukkan petunjuk
Aktifkan nilai penerima; ingat untuk memberikan default.
Solusi tersedia setelah 3 upaya
Tanda tangan manakah yang harus dimiliki metode tersebut untuk memenuhi fmt.Stringer?
func (x T) ??? {}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)ditdi dalamString()(rekursi). - Konvensi: penerima nilai untuk
String()(tidak ada mutasi, menghindari "kejutan set metode").