カスタムReaderの実装
独自のストリームを構築します
「カスタムReaderの実装」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
独自のストリームを構築する
1つのメソッドだけを持つio.Readerインターフェースを実装すれば、カスタムデータソースを作成できます。その型は、すべてのioヘルパーと組み合わせて使えるようになります。
実装するメソッド
型にRead(p []byte) (n int, err error)を実装します。pにデータを格納して件数を返し、読み取りが完了したらio.EOFを返します。
定数リーダー
ここでは、同じバイトを無限に出力し、LimitReaderで上限を設けたリーダーを扱います。
package main
import (
"fmt"
"io"
)
type constReader struct{ ch byte }
func (c constReader) Read(p []byte) (int, error) {
for i := range p {
p[i] = c.ch
}
return len(p), nil
}
func main() {
r := io.LimitReader(constReader{ch: 'A'}, 5)
data, _ := io.ReadAll(r)
fmt.Println(string(data))
}EOFの通知
データソースを使い切ったらio.EOFを返します。単独で返すことも、最後のバイト列と一緒に返すこともできます。
package main
import (
"fmt"
"io"
)
type oneShot struct{ done bool }
func (o *oneShot) Read(p []byte) (int, error) {
if o.done {
return 0, io.EOF
}
o.done = true
n := copy(p, []byte("once"))
return n, nil
}
func main() {
data, _ := io.ReadAll(&oneShot{})
fmt.Println(string(data))
}スライスからの読み取り
カスタムリーダーは、元データ内の位置を保持し、呼び出しごとに一部のデータを返すことができます。
package main
import (
"fmt"
"io"
)
type sliceReader struct {
data []byte
pos int
}
func (s *sliceReader) Read(p []byte) (int, error) {
if s.pos >= len(s.data) {
return 0, io.EOF
}
n := copy(p, s.data[s.pos:])
s.pos += n
return n, nil
}
func main() {
r := &sliceReader{data: []byte("custom")}
out, _ := io.ReadAll(r)
fmt.Println(string(out))
}変換するリーダー
別のリーダーをラップして、バイトをその場で変換します。ここでは、ストリームの各バイトを大文字に変換しています。
package main
import (
"bytes"
"fmt"
"io"
)
type upper struct{ r io.Reader }
func (u upper) 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
}
func main() {
out, _ := io.ReadAll(upper{r: bytes.NewReader([]byte("hello"))})
fmt.Println(string(out))
}バッファの長さを守る
len(p)を超えるバイトを書き込んではいけません。小さい方のスライスに合わせて範囲が制限されるcopy(p, src)を使い、コピーしたバイト数を返してください。
値レシーバーとポインタレシーバー
リーダーが位置や状態を保持する場合は、呼び出しの間も変更を維持できるようにポインタレシーバーを使います。状態を持たないリーダーでは値レシーバーを使えます。
ioヘルパーとの組み合わせ
型がio.Readerを満たしているため、io.Copy、bufio.NewReader、io.LimitReaderなどにそのまま組み込んで使えます。
package main
import (
"io"
"os"
)
type dots struct{ left int }
func (d *dots) Read(p []byte) (int, error) {
if d.left == 0 {
return 0, io.EOF
}
p[0] = '.'
d.left--
return 1, nil
}
func main() {
io.Copy(os.Stdout, &dots{left: 4})
os.Stdout.WriteString("\n")
}よくある落とし穴
io.EOFを返し忘れる(読み取りが無限に続く)len(p)を超えて書き込む- 状態を持つリーダーで値レシーバーを使う
カスタムリーダーを使う理由
カスタムリーダーを使うと、ジェネレーター、デコーダー、レートリミッター、暗号化ストリームなど、あらゆるソースをGoの汎用的なI/Oエコシステムに適応させられます。
クイックチェック
カスタムリーダーの知識を確認しましょう。
まとめ
独自のストリームを構築する方法を学びました。
Read(p []byte) (int, error)を実装しますcopyを使い、len(p)を守ります- 完了したら
io.EOFを返します - 状態を持つリーダーにはポインタレシーバーを使います
- すべてのioヘルパーと自由に組み合わせられます
よくある質問
「カスタムReaderの実装」レッスンは無料ですか?
はい。「カスタムReaderの実装」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「カスタムReaderの実装」で何を学びますか?
独自のストリームを構築します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「カスタムReaderの実装」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Readerインターフェース
- Writerインターフェース
- ioユーティリティ関数
- カスタムReaderの実装