関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。忘れないうちにメモメモ。。。
Go 1.26で bytes.Buffer.Peekが追加されていたのですね。
ソケットのMSG_PEEKのように、データは読み出すけど、内部のバッファはそのままとなります。
データはそのままで先頭Nバイトを確認したい場合とかによく利用しますね。
Peekしたいバイト数を引数で指定しますが、データが足りない場合は io.EOF が返ります。
また、内部バッファをそのままスライスにして返してきてくるので、bytes.Buffer.Peek で取得したスライスは次のRead/Writeまでが有効期限となります。必要であれば自力でcopyする必要がある。まあ、基本的にPeekしたデータを長く利用することってありませんが。
以下、ドキュメントの文章を転載。
Peek returns the next n bytes without advancing the buffer. If Peek returns fewer than n bytes, it also returns io.EOF. The slice is only valid until the next call to a read or write method. The slice aliases the buffer content at least until the next buffer modification, so immediate changes to the slice will affect the result of future reads.
(Peekはバッファを進めずに次のnバイトを返します。Peekがnバイト未満のバイト数を返す場合、io.EOFも返します。スライスは、次のreadメソッドまたはwriteメソッドの呼び出しまで有効です。スライスは、少なくとも次のバッファ変更までバッファの内容のエイリアスとなるため、スライスへの即時の変更は、以降の読み取り結果に影響します。)
サンプル
package main import ( "bytes" "log" ) func main() { log.SetFlags(0) var ( buf = new(bytes.Buffer) err error ) if _, err = buf.WriteString("helloworld"); err != nil { log.Panic(err) } log.Printf("[Length] Len: %d", buf.Len()) // Go 1.26より bytes.Buffer.Peek() が追加された // ソケットのMSG_PEEKのように、データは読み出すけど内部バッファは変わらない。 var ( peekBytes []byte ) if peekBytes, err = buf.Peek(5); err != nil { log.Panic(err) } log.Printf("[Peek ] %s (%s)", peekBytes, buf.Bytes()) log.Printf("[Length] Len: %d", buf.Len()) // Readすると当然変わる var ( readBytes = make([]byte, len(peekBytes)) ) if _, err = buf.Read(readBytes); err != nil { log.Panic(err) } log.Printf("[Read ] %s (%s)", readBytes, buf.Bytes()) log.Printf("[Length] Len: %d", buf.Len()) }
実行すると以下のようになります。
$ go1.26rc2 version go version go1.26rc2 linux/amd64 $ task [Length] Len: 10 [Peek ] hello (helloworld) [Length] Len: 10 [Read ] hello (world) [Length] Len: 5
Peekを呼び出した場合は内部のバッファは変化していませんね。
参考情報
個人的Goのおすすめ書籍
個人的に読んでとても勉強になった書籍さんたちです。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。






