🔥 io.Reader 인터페이스

283자
4분

Go 언어의 io 패키지는 데이터 스트림의 읽기 끝을 나타내는 io.Reader 인터페이스를 정의하고 있어요. 이 인터페이스는 파일, 네트워크 연결, 압축기, 암호화기 등 다양한 구현체를 Go 표준 라이브러리에서 제공하고 있죠.

io.Reader 인터페이스는 다음과 같은 Read 메서드를 가지고 있습니다.

func (T) Read(b []byte) (n int, err error)
 
go

Read 메서드는 주어진 바이트 슬라이스에 데이터를 채우고, 채워진 바이트 수와 에러 값을 반환해요. 스트림의 끝에 도달하면 io.EOF 에러를 반환하죠.

예제 코드에서는 strings.Reader를 생성하고, 8바이트씩 출력을 소비하는 과정을 보여주고 있어요. 코드를 한 줄씩 살펴볼까요?

package main
 
import (
    "fmt"
    "io"
    "strings"
)
 
func main() {
    // 문자열로부터 Reader를 생성합니다.
    r := strings.NewReader("Hello, Reader!")
 
    // 8바이트 크기의 버퍼를 생성합니다.
    b := make([]byte, 8)
 
    for {
        // Reader에서 최대 len(b) 바이트를 읽어옵니다.
        n, err := r.Read(b)
 
        // 읽어온 바이트 수, 에러, 버퍼 내용을 출력합니다.
        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
 
        // 실제로 읽은 바이트 수만큼 버퍼를 슬라이싱하여 출력합니다.
        fmt.Printf("b[:n] = %q\n", b[:n])
 
        // 파일 끝에 도달하면 루프를 종료합니다.
        if err == io.EOF {
            break
        }
    }
}
 
go
  1. strings.NewReader 함수를 사용하여 문자열로부터 Reader를 생성해요.
  2. 8바이트 크기의 버퍼 b를 만들어요.
  3. 무한 루프를 시작하죠.
    • Read 메서드를 호출하여 최대 len(b) 바이트를 읽어옵니다.
    • 읽어온 바이트 수 n, 에러 err, 버퍼 내용 b를 출력해요.
    • 실제로 읽은 바이트 수만큼 버퍼를 슬라이싱하여 출력합니다.
    • 파일 끝(io.EOF)에 도달하면 루프를 종료해요.

이런 식으로 io.Reader 인터페이스를 사용하면, 다양한 데이터 소스로부터 일관된 방식으로 데이터를 읽어올 수 있답니다. 코드의 재사용성과 유연성이 높아지는 거죠.

버퍼 크기에 따라 한 번에 읽어오는 데이터의 양이 달라질 수 있어요. 버퍼 크기를 적절히 조절하면 읽기 성능을 최적화할 수 있습니다.

lecture image

이렇게 io.Reader 인터페이스는 데이터 소스와 애플리케이션 코드 사이의 추상화 계층으로 동작하는 셈이에요. 다양한 구현체를 표준 인터페이스로 다룰 수 있어 코드의 유연성과 가독성이 향상된답니다.