関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。忘れないようにここにメモメモ。。。
bytes.Buffer はとても便利な型ですね。個人的にはGoで利用している型のトップ3には余裕で入っています。
io.Readerにもなれるし、io.Writerにもなれる。でも、io.Closerを実装していないので、io.ReadWriteCloserにはなれない。
通信処理を書く際に net.Conn を使いますが、この net.Conn さんは io.ReadWriteCloser を実装しています。ついでに os.File さんも実装しています。
なので、これらを使った処理をテスト可能にする際に io.ReadWriteCloser で処理するようにすると、テスト時にモックが渡しやすい。
で、テスト時の値には bytes.Buffer を使いたい。
ラップした型を用意して、空実装のCloseメソッドを用意すれば事足りるのですが、限定的な場面で利用するだけのときは匿名構造体を使ったほうが楽です。
サンプル
main.go
package bufferop import ( "bytes" "io" "os" ) // ToReadWriteCloser は、bytes.Buffer を io.ReadWriteCloser に変換するサンプルです. // // bytes.Bufferは、既に io.Reader と io.Writer を実装していますが // io.Closer は実装していません。そのため、そのままでは // os.File や net.Conn のように io.ReadWriteCloser としては利用できません。 // // bytes.Bufferをラップし、Closeメソッドを空実装した型を別途用意すれば良いのですが面倒です。 // リミテッドな使い方(特定の関数に渡したいだけ)の場合は、匿名構造体と io.NopCloser を利用した方が楽です。 // // # REFERENCES // - https://zenn.dev/nobonobo/articles/297dc5cbc554d6 func ToReadWriteCloser() error { // funcs var ( // 変換 c = func(b *bytes.Buffer) io.ReadWriteCloser { // 匿名構造体を使って、io.ReadWriteCloser の実装を用意。 // io.ReadWriteCloser は io.Reader, io.Writer, io.Closer の合成インターフェースとなる。 // なので、その3つを実装していれば良いことになる。 return &struct { io.ReadCloser // io.Reader と io.Closer io.Writer // io.Writer }{ io.NopCloser(b), // io.ReaderはBufferが実装済み。io.Closerは空実装。 b, // io.WriterはBufferが実装済み。 } } // 書き込み w = func(rwc io.ReadWriteCloser) { _, _ = rwc.Write([]byte("hello\n")) } // 読み込み r = func(rwc io.ReadWriteCloser) { io.Copy(os.Stdout, rwc) } ) var ( b bytes.Buffer rwc = c(&b) ) w(rwc) r(rwc) return nil }
shell
実行すると以下のように出力されます。
$ task task: [build] go build -o "/workspace/try-golang/try-golang" . task: [run] ./try-golang -onetime ENTER EXAMPLE NAME: bufferop_to_readwritecloser [Name] "bufferop_to_readwritecloser" hello [Elapsed] 40.39µs
参考情報
try-golang/examples/basic/bufferop/to_readwritecloser.go at main · devlights/try-golang · GitHub
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。