0Pricing
Go Academy · レッスン

大容量ファイルのストリーミング

すべてを読み込まずにファイルを処理します

「大容量ファイルのストリーミング」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

すべて読み込むことの問題

数GBのファイルをos.ReadFileでメモリに読み込むと、RAMを使い果たす可能性があります。代わりにストリーミング処理を行い、データが到着したらチャンク単位で処理してください。

ストリーミングの考え方

ストリーミングとは、一度にメモリ上に保持するデータを小さな範囲に限定することです。バッファリングと組み合わせると、メモリ使用量を一定に保ったまま、任意の大きさの入力を処理できます。

Scannerによる行単位の処理

テキストの場合、リーダーに対してbufio.Scannerを使うと、ファイルサイズに関係なく1行ずつ処理できます。ここではstrings.Readerでファイルをシミュレートしています。

package main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	src := strings.NewReader("alpha\nbeta\ngamma")
	s := bufio.NewScanner(src)
	for s.Scan() {
		fmt.Println("processed:", s.Text())
	}
}

読み込まずにカウントする

メモリ上にほとんどデータを保持せずに、大規模なストリームの統計を計算できます。

package main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	s := bufio.NewScanner(strings.NewReader("a\nbb\nccc"))
	total := 0
	for s.Scan() {
		total += len(s.Text())
	}
	fmt.Println("total chars:", total)
}

固定サイズのチャンク

バイナリデータの場合は、Readを使って固定サイズのバッファに読み込みます。nは、格納されたバイト数を示します。

package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	src := strings.NewReader("0123456789")
	buf := make([]byte, 4)
	for {
		n, err := src.Read(buf)
		if n > 0 {
			fmt.Printf("chunk: %s\n", buf[:n])
		}
		if err == io.EOF {
			break
		}
	}
}

ストリーミングにはio.Copyを使う

io.Copy(dst, src)は小さな内部バッファを使って、リーダーからライターへすべてのデータをストリーミングします。データ全体を読み込む必要はありません。

package main

import (
	"io"
	"os"
	"strings"
)

func main() {
	src := strings.NewReader("streamed straight through\n")
	io.Copy(os.Stdout, src)
}

ReaderとWriterのバッファを組み合わせる

両端をbufioでラップすると、効率的なストリーミング変換を行えます。バッファ付きで読み取り、処理し、バッファ付きで書き込んで、フラッシュします。

package main

import (
	"bufio"
	"os"
	"strings"
)

func main() {
	r := bufio.NewScanner(strings.NewReader("one\ntwo"))
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()
	for r.Scan() {
		w.WriteString(r.Text() + "!\n")
	}
}

メモリ使用量が一定になる保証

バッファサイズが固定されているため、入力が1KBでも1TBでもメモリ使用量は変わりません。これがストリーミングの最大の利点です。

よくあるミスを避ける

  • 大きなファイルに対してos.ReadFileを呼び出さない
  • エラーを確認する前に、必ずnバイトを処理する
  • バッファ付きWriterではFlush()を忘れない

ストリームを変換する

ここではストリームから各行を読み取りながら大文字に変換し、一度にメモリ上に保持するのは1行だけにしています。

package main

import (
	"bufio"
	"os"
	"strings"
)

func main() {
	s := bufio.NewScanner(strings.NewReader("hi\nthere"))
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()
	for s.Scan() {
		w.WriteString(strings.ToUpper(s.Text()) + "\n")
	}
}

ストリーミングを使う場面

入力サイズが大きい、または不明な場合や、段階的に処理できる場合はストリーミングを使用します。すべてのデータを同時に必要とする小さく上限の決まったデータの場合に限り、全体を読み込んでください。

理解度チェック

ストリーミングについての知識を確認しましょう。

まとめ

データ全体を読み込まずに大規模なデータを処理する方法を学びました。

  • テキストを行単位で処理するにはScanner
  • バイナリデータをチャンク単位で処理するには固定サイズのRead
  • ストリーム間の処理にはio.Copy
  • 両端をバッファリングし、Writerをフラッシュして、メモリ使用量を一定に保つ

よくある質問

「大容量ファイルのストリーミング」レッスンは無料ですか?

はい。「大容量ファイルのストリーミング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「大容量ファイルのストリーミング」で何を学びますか?

すべてを読み込まずにファイルを処理します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「大容量ファイルのストリーミング」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. バッファ付きReader
  2. Scanner
  3. バッファ付きWriter
  4. 大容量ファイルのストリーミング
← Go Academyに戻る