私はencoding/gob
まだパッケージを使用していません (クールに見えます。そのためのプロジェクトを見つける必要があるかもしれません)。しかし、godoc を読むと、各エンコーディングは、最初から最後までデコードされることが期待される単一のレコードであるように思えます。つまりEncode
、ストリームを作成すると、結果のバイトはストリーム全体を最初から最後まで考慮した完全なセットになります。後で再度エンコードして追加することはできません。
godoc は、エンコードされたgob
ものは自己記述的であると述べています。エンコードされたストリームの最初に、フィールド名を含め、その後に続くデータ セットの構造体、型など全体が記述されます。次に、バイト ストリームに続くのは、エクスポートされたフィールドの値のサイズとバイト表現です。
次に、ドキュメントから省略されているのは、渡されようとしている各フィールドを含め、ストリームが最初にそれ自体を自己記述しているためであると想定できDecoder
ます。はDecoder
、最初に記述されたものしか認識しないため、記述された後に追加された連続するバイトを認識しません。したがって、そのエラー メッセージpanic: extra data in buffer
は正確です。
Playground の例では、同じエンコーダー インスタンスに 2 回エンコードしてから、ファイルを閉じています。正確に 2 つのレコードを渡し、2 つのレコードをエンコードしているため、エンコーダーの単一のインスタンスが 2 つの呼び出しを単一のエンコードされたストリームと見なす可能性があるため、これは機能する可能性があります。Encode
次に、ファイル io のストリームを閉じると、gob
これで完了です。ストリームは (2 つのタイプで送信したとしても) 単一のレコードとして扱われます。
デコード関数でも同じで、同じストリームから X 回読み取っています。ただし、ファイルを閉じるときに単一のレコードを書き込んでいます。実際には、その単一のレコードに2つのタイプがあります。したがって、2 を読み取るときに機能し、正確に 2 が機能するのはなぜですか。ただし、2 を超える読み取りを行うと失敗します。
これを単一のファイルに保存する場合の解決策は、完全な「書き込み」またはエンコーダー インスタンス/セッションごとに独自のインデックスを作成する必要があることです。ディスクに書き込まれた各エントリを「開始」および「終了」マーカーでラップまたは定義できる独自の Block メソッドを形成するものもあります。そうすれば、ファイルを読み戻すときに、開始/終了マーカーにより、どのバッファーを割り当てるかが正確にわかります。バッファに単一のレコードがあれば、gob を使用Decoder
してそれをデコードします。そして、書き込みごとにファイルを閉じます。
このようなマーカーに使用するパターンは次のようなものです。
uint64:uint64
uint64:uint64
...
最初のエントリは開始バイト番号で、コロンで区切られた 2 番目のエントリはその長さです。私は通常、これを適切に呼び出された別のファイルに保存しますindexes
。そうすれば、メモリにすばやく読み込むことができ、開始アドレスと終了アドレスがバイト ストリームのどこにあるかを正確に把握して、大きなファイルをストリーミングできます。
もう 1 つのオプションはgob
、ファイル システムのディレクトリ構造を使用して適切に整理することで、それぞれを独自のファイルに保存することです (または、たとえば、ディレクトリを使用して型を定義することもできます)。そして、各ファイルの存在は単一のレコードです。これは、イベント ソーシング手法からレンダリングされた json を使用して、何百万ものファイルをディレクトリに整理して保存する方法です。
gob
要約すると、データの最初から最後までの完全なセット、つまり単一の「レコード」のように思えます。複数のエンコーディング/複数のゴブを保存する場合は、独自のインデックスを作成して、gob
保存するときに各バイトの開始とサイズ/終了を追跡する必要があります。次に、Decode
各エントリを個別に作成します。