PHpullh
학습 라이브러리/Go/io.Reader & io.Writer 인터페이스

GO · 패턴

io.Reader & io.Writer 인터페이스

Go 표준 라이브러리의 가장 강력한 인터페이스. 파이프라인과 데코레이터 패턴의 기반.

패턴고급io.Readerio.WriterTeeReaderMultiWriterdecorator

핵심 설명

Go 표준 라이브러리의 가장 강력한 인터페이스. 파이프라인과 데코레이터 패턴의 기반.

Go code

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"
)

// 커스텀 io.Reader 구현
type UpperReader struct {
	r io.Reader
}

func (u *UpperReader) Read(p []byte) (int, error) {
	n, err := u.r.Read(p)
	for i := 0; i < n; i++ {
		if p[i] >= 'a' && p[i] <= 'z' {
			p[i] -= 32
		}
	}
	return n, err
}

// 커스텀 io.Writer 구현
type CountWriter struct {
	w    io.Writer
	n    int64
}

func (c *CountWriter) Write(p []byte) (int, error) {
	n, err := c.w.Write(p)
	c.n += int64(n)
	return n, err
}

// io.TeeReader — 읽으면서 동시에 쓰기
func teeExample() {
	r := strings.NewReader("Hello, Go!")
	var buf bytes.Buffer
	tee := io.TeeReader(r, &buf)

	data, _ := io.ReadAll(tee)
	fmt.Println("읽음:", string(data))
	fmt.Println("복사:", buf.String())
}

// io.MultiWriter — 여러 Writer에 동시 쓰기
func multiWriterExample() {
	var b1, b2 bytes.Buffer
	mw := io.MultiWriter(&b1, &b2)
	fmt.Fprintln(mw, "동시에 두 곳에 쓰기")
	fmt.Println(b1.String() == b2.String()) // true
}

func main() {
	// UpperReader 데코레이터
	r := strings.NewReader("hello world")
	upper := &UpperReader{r: r}
	buf := make([]byte, 64)
	n, _ := upper.Read(buf)
	fmt.Println(string(buf[:n])) // HELLO WORLD

	// CountWriter
	var buf2 bytes.Buffer
	cw := &CountWriter{w: &buf2}
	fmt.Fprintln(cw, "bytes counted")
	fmt.Println("쓴 바이트:", cw.n)

	teeExample()
	multiWriterExample()

	// bufio로 성능 향상
	r2 := strings.NewReader("line1
line2
line3")
	scanner := bufio.NewScanner(r2)
	for scanner.Scan() { fmt.Println(scanner.Text()) }
}

학습 팁

io.Readerio.Writer로 함수를 설계하면 테스트 시 strings.NewReaderbytes.Buffer로 쉽게 대체할 수 있습니다.

주의할 점

Read()n > 0이면서 동시에 err != nil을 반환할 수 있습니다. n > 0인 데이터를 먼저 처리한 후 에러를 확인하세요.

자주 묻는 질문

io.Reader & io.Writer 인터페이스란 무엇인가요?

Go 표준 라이브러리의 가장 강력한 인터페이스. 파이프라인과 데코레이터 패턴의 기반.

io.Reader & io.Writer 인터페이스 학습 시 주의할 점은 무엇인가요?

Read() 가 n > 0 이면서 동시에 err != nil 을 반환할 수 있습니다. n > 0인 데이터를 먼저 처리한 후 에러를 확인하세요.