본문 바로가기

프로그래밍/golang

[Golang] io 패키지 MultiWriter, MultiReader 예제

 

백엔드 개발에서 데이터 스트림을 효율적으로 제어하는 것은 성능과 직결이 됩니다.

io 패키지 활용 예제를 함께 살펴봅시다.

 

1. MultiWriter

  • 왜 쓰는가?
    로그를 남기거나, 파일을 업로드 할 경우, 동일한 데이터로 여러 일들을 함께 처리해야할 상황
    데이터를 두 번 읽거나 반복문을 사용하는 것 대신, "MultiWriter" 를 활용해 한 번의 쓰기 동작으로
    여러 목적지에 데이터를 전달 할 수 있습니다.
    즉 데이터를 한번 읽고, 여러 목적지에 동시에 쓰기 기능을 제공합니다.

    • 로깅 : 표준출력 및 파일 기록
    • 무결성 : 파일 업로드 및 해시(Checksum) 계산
    • 백업 : 주 저장소 와 보조 저장소 동시 저장

- 예제 코드

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
)

func main() {
	inputData := "Backend developer Reo's Tech Log: io.MultiWriter Example Data"
	reader := strings.NewReader(inputData)

	consoleWriter := os.Stdout

	logFile, err := os.Create("process.log")
	if err != nil {
		log.Fatalf("Failed to create file: %v", err)
	}
	defer logFile.Close()

	hashWriter := sha256.New()

	multi := io.MultiWriter(consoleWriter, logFile, hashWriter)

	written, err := io.Copy(multi, reader)
	if err != nil {
		log.Fatalf("Error occurred during writing: %v", err)
	}

	fmt.Printf("\nWriting completed (%d bytes)\n", written)

	hashInBytes := hashWriter.Sum(nil)
	hashString := hex.EncodeToString(hashInBytes)
	fmt.Printf("Generated SHA256 Hash: %s\n", hashString)
}

 

 

2. MultiReader

  • 왜 쓰는가?
    여러 데이터 소스를 순서대로 읽어야 할 경우, 이를 커다란 스트림으로 통합하기 위해서 사용합니다.
    물리적으로 데이터를 합쳐서 새로운 메모리 공간에 할당하는 대신에, 논리적으로 연결만 해서 메모리 효율을 올릴 수 있습니다.

    • 헤더와 바디 결합 : 고정된 프로토콜 헤더와 실제 데이터를 합쳐서 전송할 경우
    • 파일 병합 처리 : 여러개로 분할된 로그 파일 하나의 스트림으로 읽어서 분석할 경우
    • 데이터 주입 : 기존 데이터 앞뒤로 특정 문구나 식별자를 붙여서 전달 할 때

 

- 예제 코드

package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"strings"
)

func main() {
	header := strings.NewReader("--- START OF LOG ---\n")
	body := strings.NewReader("Task: Process Data\nStatus: Success\n")
	footer := strings.NewReader("--- END OF LOG ---\n")

	combinedReader := io.MultiReader(header, body, footer)

	fmt.Println("Reading from combined stream:")

	written, err := io.Copy(os.Stdout, combinedReader)
	if err != nil {
		log.Fatalf("Error occurred during reading: %v", err)
	}
	fmt.Printf("\nTotal bytes read: %d\n", written)
}

 

 

 

3. 전체 코드

https://github.com/reochoi109/go-handbook/blob/main/io/advanced/multiWriter/main.go

 

go-handbook/io/advanced/multiWriter/main.go at main · reochoi109/go-handbook

A personal handbook of Go patterns and best practices. Lightweight, practical code snippets for real-world backend development. - reochoi109/go-handbook

github.com