Interface sebagai Kontrak
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 27 dari 107.
Menganggap interface sebagai kontrak membantumu merancang program Go yang lebih baik. Saat sebuah fungsi menerima tipe interface, maksudnya: "Aku tidak peduli tipe konkret apa yang kamu berikan, selama tipe itu memenuhi kontrak ini."
Pemikiran berbasis kontrak ini memungkinkan kamu menulis fungsi yang berfokus pada perilaku, bukan tipe tertentu. Pertimbangkan fungsi yang perlu memproses data dari berbagai sumber:
type DataSource interface {
FetchData() string
}
func ProcessData(src DataSource) {
data := src.FetchData()
fmt.Println("Processing:", data)
}Fungsi ProcessData tidak tahu atau peduli apakah menerima koneksi database, client API, atau pembaca file. Fungsi ini hanya membutuhkan input yang bisa FetchData(). Tipe apa pun yang memenuhi kontrak ini bisa digunakan.
type Database struct{ ConnectionString string }
func (d Database) FetchData() string { return "data from DB" }
type APIClient struct{ Endpoint string }
func (a APIClient) FetchData() string { return "data from API" }
func main() {
db := Database{ConnectionString: "localhost"}
api := APIClient{Endpoint: "https://api.example.com"}
ProcessData(db) // Berhasil!
ProcessData(api) // Ini juga berhasil!
}Pendekatan kontrak ini juga membuat kodemu lebih mudah diuji. Saat pengujian, kamu bisa membuat tipe mock yang memenuhi interface tanpa memerlukan database atau koneksi jaringan sungguhan. Fungsi yang diuji tidak mengetahui perbedaannya karena kontrak tersebut terpenuhi.
Tantangan
MudahMari kita buat sistem notifikasi yang menunjukkan cara interface berfungsi sebagai kontrak. Kamu akan membuat interface Notifier yang mendefinisikan arti mengirim notifikasi, lalu mengimplementasikan beberapa saluran notifikasi yang semuanya mematuhi kontrak ini.
Kamu akan menyusun kodemu dalam dua file:
notifiers.go: Definisikan interfaceNotifierdengan satu methodNotify(message string) string. Lalu buat tiga struct berbeda yang memenuhi kontrak ini:ConsoleNotifierdengan fieldPrefixFileNotifierdengan fieldFilenameWebhookNotifierdengan fieldURL
Notifyuntuk mengembalikan string yang menjelaskan cara notifikasi akan dikirim.main.go: Buat fungsi bernamaBroadcastAlertyang menerima slice berisi nilaiNotifierdan string pesan. Fungsi ini harus memanggilNotifypada setiap notifier dan mencetak hasilnya. Baca konfigurasi dari input, buat ketiga tipe notifier, lalu sebarkan peringatan melalui semuanya.
Input berikut akan diberikan:
- Baris 1: Prefiks console
- Baris 2: Nama file
- Baris 3: URL webhook
- Baris 4: Pesan peringatan
Method Notify-mu harus mengembalikan string dengan format berikut:
- ConsoleNotifier:
[Prefix] [message] - FileNotifier:
Writing to [Filename]: [message] - WebhookNotifier:
POST [URL]: [message]
Misalnya, jika inputnya adalah ALERT:, log.txt, https://hooks.example.com, dan Server down!, output-mu seharusnya:
ALERT: Server down!
Writing to log.txt: Server down!
POST https://hooks.example.com: Server down!Keunggulan desain ini adalah fungsi BroadcastAlert-mu tidak mengetahui atau memedulikan tipe notifier tertentu. Fungsi ini hanya membutuhkan setiap notifier untuk memenuhi kontrak Notifier. Kamu dapat menambahkan SlackNotifier atau EmailNotifier nanti tanpa mengubah fungsi penyebaran sama sekali.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
)
// BroadcastAlert mengirim pesan melalui semua notifier
// TODO: Implementasikan fungsi ini untuk:
// - Menerima slice berisi nilai Notifier dan string pesan
// - Memanggil Notify pada setiap notifier dan mencetak hasilnya
func BroadcastAlert(notifiers []Notifier, message string) {
// TODO: Lakukan perulangan pada notifiers dan cetak setiap hasil notifikasi
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Baca prefiks konsol
scanner.Scan()
prefix := scanner.Text()
// Baca nama file
scanner.Scan()
filename := scanner.Text()
// Baca URL webhook
scanner.Scan()
url := scanner.Text()
// Baca pesan peringatan
scanner.Scan()
message := scanner.Text()
// TODO: Buat instance dari ketiga tipe notifier
// - ConsoleNotifier dengan prefiks
// - FileNotifier dengan nama file
// - WebhookNotifier dengan URL
// TODO: Buat slice berisi nilai Notifier untuk ketiga notifier
// TODO: Panggil BroadcastAlert dengan notifiers dan message
_ = prefix
_ = filename
_ = url
_ = message
fmt.Println("TODO: Implement the solution")
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online