Menu
Coddy logo textTech

io.Reader ve io.Writer

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 73 / 107.

Go'nun standart kütüphanesi, iki temel arayüz aracılığıyla arayüz tabanlı tasarımı sergiler: io.Reader ve io.Writer. Bu basit arayüzler, dosya işlemlerinden ağ iletişimine kadar her şeye güç verir.

io.Reader arayüzü yalnızca bir yöntem gerektirir:

type Reader interface {
    Read(p []byte) (n int, err error)
}

Dilim içine en fazla len(p) bayt okur ve kaç bayt okunduğunu döndürür. Benzer şekilde, io.Writer şunları tanımlar:

type Writer interface {
    Write(p []byte) (n int, err error)
}

Bu yöntemleri uygulayan herhangi bir tür, tüm G/Ç ekosistemiyle çalışır.

İşte io.Reader arayüzünü uygulayan özel bir tür:

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
}

Artık bu özel okuyucu, io.Reader bekleyen herhangi bir işlevle çalışır:

reader := &RepeatReader{Char: 'A', Count: 5}
data, _ := io.ReadAll(reader)
fmt.Println(string(data))  // AAAAA

Bu tasarım, io.Reader veya io.Writer kabul eden işlevler yazmanıza olanak tanır; böylece bunlar dosyalarla, ağ bağlantılarıyla, arabelleklerle veya herhangi bir özel uygulamayla çalışabilir.

challenge icon

Görev

Kolay

io.Reader ve io.Writer arayüzlerini uygulayan özel bir metin akışı işlemcisi oluşturalım! Metin içlerinden geçerken onu dönüştürebilen türler oluşturacak ve bu temel arayüzlerin güçlü G/Ç bileşimi sağlamasını göstereceksin.

Kodunu iki dosyaya ayıracaksın:

  • streams.go: Özel okuyucu ve yazıcı türlerini tanımla.

    Bir dizeyi saran ve kaç bayt okunduğunu takip eden bir CountingReader yapısı oluştur. Kaynak dize ve konum izleyici alanlarına sahip olmalı. Kaynaktan sağlanan dilime baytları okuyan, konumu güncelleyen ve kaynak tükendiğinde Read(p []byte) (int, error) döndüren io.EOF metodunu uygula.

    Yazılan verileri toplayan ve büyük harfe dönüştüren bir UppercaseWriter yapısı oluştur. Birikmiş sonucu dahili olarak saklamalıdır. Gelen baytları büyük harfe dönüştüren ve saklayan Write(p []byte) (int, error) metodunu uygula. Birikmiş büyük harfli metni almak için Result() string metodunu ekle.

    Türlerini uygun şekilde başlatmak için NewCountingReader(source string) *CountingReader ve NewUppercaseWriter() *UppercaseWriter kurucu işlevlerini oluştur.

  • main.go: Özel G/Ç türlerinin standart kitaplıkla birlikte çalışmasını göster.

    Bir dize girdisi oku, ardından tüm verileri okumak için CountingReader türünü io.ReadAll ile kullan. Bu verileri, UppercaseWriter metodunu kullanarak Write üzerinden geçir.

    Sonuçları şu biçimde yazdır:

    Original: [input]
    Uppercase: [result from writer]
    Bytes read: [total bytes]

Aşağıdaki girdi sağlanacaktır:

  • Tek bir metin satırı

Örneğin, şu verildiğinde:

Hello World

Çıktın şöyle olmalı:

Original: Hello World
Uppercase: HELLO WORLD
Bytes read: 11

Ve şu verildiğinde:

Go interfaces are powerful

Çıktın şöyle olmalı:

Original: Go interfaces are powerful
Uppercase: GO INTERFACES ARE POWERFUL
Bytes read: 26

Temel çıkarım şudur: CountingReader, io.ReadAll uyguladığı için io.Reader ile sorunsuz şekilde çalışır. Go ekosisteminde io.Reader kabul eden herhangi bir işlev, özel türünle çalışır: arayüz tabanlı tasarımın gücü budur.

Kendin dene

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	// Girdiyi oku
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	// Varsa sondaki satır sonunu kaldır
	if len(input) > 0 && input[len(input)-1] == '\n' {
		input = input[:len(input)-1]
	}

	// TODO: Girdi dizesiyle bir CountingReader oluştur
	// countingReader := NewCountingReader(input)

	// TODO: CountingReader'ınızdan tüm verileri okumak için io.ReadAll kullanın
	// data, err := io.ReadAll(countingReader)

	// TODO: Bir UppercaseWriter oluştur
	// upperWriter := NewUppercaseWriter()

	// TODO: Veriyi UppercaseWriter'ınıza yazın
	// upperWriter.Write(data)

	// TODO: Sonuçları gerekli formatta yazdırın:
	// Original: [input]
	// Uppercase: [writer'dan gelen sonuç]
	// Bytes read: [toplam bayt]

	// Kullanılmayan import hatasını önlemek için yer tutucu - uygularken kaldırın
	_ = io.EOF
	fmt.Println("Original:", input)
	// fmt.Println("Uppercase:", upperWriter.Result())
	// fmt.Println("Bytes read:", countingReader.Position)
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Go derleyicisi