io.Reader & io.Writer
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 73 dari 107.
standard library Go menunjukkan desain berbasis interface melalui dua interface dasar: io.Reader dan io.Writer. Interface sederhana ini mendukung segala hal, mulai dari operasi file hingga komunikasi jaringan.
Interface io.Reader hanya memerlukan satu method:
type Reader interface {
Read(p []byte) (n int, err error)
}Ini membaca hingga len(p) byte ke dalam slice dan mengembalikan jumlah byte yang dibaca. Demikian pula, io.Writer mendefinisikan:
type Writer interface {
Write(p []byte) (n int, err error)
}Tipe apa pun yang mengimplementasikan method ini dapat digunakan di seluruh ekosistem I/O.
Berikut tipe kustom yang mengimplementasikan io.Reader:
type RepeatReader struct {
Char byte
Count int
pos int
}
func (r *RepeatReader) Read(p []byte) (int, error) {
if r.pos >= r.Count {
return 0, io.EOF
}
n := 0
for n < len(p) && r.pos < r.Count {
p[n] = r.Char
n++
r.pos++
}
return n, nil
}Sekarang reader khusus ini berfungsi dengan fungsi apa pun yang mengharapkan io.Reader:
reader := &RepeatReader{Char: 'A', Count: 5}
data, _ := io.ReadAll(reader)
fmt.Println(string(data)) // AAAAADesain ini memungkinkan kamu menulis fungsi yang menerima io.Reader atau io.Writer, sehingga fungsi tersebut dapat digunakan dengan file, koneksi jaringan, buffer, atau implementasi kustom apa pun.
Tantangan
MudahMari buat pemroses stream teks khusus yang mengimplementasikan interface io.Reader dan io.Writer! Kamu akan membuat tipe yang dapat mengubah teks saat teks mengalir melaluinya, untuk menunjukkan bagaimana interface dasar ini memungkinkan komposisi I/O yang andal.
Kamu akan menyusun kodemu dalam dua file:
streams.go: Definisikan tipe reader dan writer khususmu.Buat struct
CountingReaderyang membungkus sebuah string dan melacak jumlah byte yang telah dibaca. Struct ini harus memiliki field untuk string sumber dan pelacak posisi. Implementasikan methodRead(p []byte) (int, error)yang membaca byte dari sumber ke dalam slice yang diberikan, memperbarui posisi, dan mengembalikanio.EOFsaat sumber habis.Buat struct
UppercaseWriteryang mengumpulkan data yang ditulis dan mengubahnya menjadi huruf kapital. Struct ini harus menyimpan hasil yang terkumpul secara internal. Implementasikan methodWrite(p []byte) (int, error)yang mengubah byte yang masuk menjadi huruf kapital dan menyimpannya. Tambahkan methodResult() stringuntuk mengambil teks huruf kapital yang terkumpul.Buat fungsi konstruktor
NewCountingReader(source string) *CountingReaderdanNewUppercaseWriter() *UppercaseWriteruntuk menginisialisasi tipemu dengan benar.main.go: Tunjukkan cara tipe I/O khususmu bekerja dengan standard library.Baca input string, lalu gunakan
CountingReadermilikmu bersamaio.ReadAlluntuk membaca semua data. Teruskan data tersebut melaluiUppercaseWritermilikmu menggunakan methodWrite.Cetak hasil dengan format ini:
Original: [input] Uppercase: [result from writer] Bytes read: [total bytes]
Input berikut akan diberikan:
- Satu baris teks
Contohnya, jika diberikan:
Hello WorldOutputmu harus berupa:
Original: Hello World
Uppercase: HELLO WORLD
Bytes read: 11Dan jika diberikan:
Go interfaces are powerfulOutputmu harus berupa:
Original: Go interfaces are powerful
Uppercase: GO INTERFACES ARE POWERFUL
Bytes read: 26Inti pentingnya adalah CountingReader milikmu dapat bekerja dengan lancar bersama io.ReadAll karena mengimplementasikan io.Reader. Fungsi apa pun dalam ekosistem Go yang menerima io.Reader akan bekerja dengan tipe khususmu. Itulah keunggulan desain berbasis interface.
Coba sendiri
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
// Baca input
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
// Hapus karakter baris baru di akhir jika ada
if len(input) > 0 && input[len(input)-1] == '\n' {
input = input[:len(input)-1]
}
// TODO: Buat CountingReader dengan string input
// countingReader := NewCountingReader(input)
// TODO: Gunakan io.ReadAll untuk membaca semua data dari CountingReader-mu
// data, err := io.ReadAll(countingReader)
// TODO: Buat UppercaseWriter
// upperWriter := NewUppercaseWriter()
// TODO: Tulis data ke UppercaseWriter-mu
// upperWriter.Write(data)
// TODO: Cetak hasilnya dalam format yang diminta:
// Asli: [input]
// Huruf besar: [hasil dari penulis]
// Byte yang dibaca: [total byte]
// Kode sementara untuk menghindari error import yang tidak digunakan. Hapus saat kamu mengimplementasikannya.
_ = io.EOF
fmt.Println("Original:", input)
// fmt.Println("Uppercase:", upperWriter.Result())
// fmt.Println("Bytes read:", countingReader.Position)
}
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 File11Pustaka Standar & OOP
io.Reader & io.Writersort.InterfaceAntarmuka fmt.Stringerencoding/json dengan StructAntarmuka http.HandlerRingkasan, Model REST API3Pointer 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