4

このGo Data Structuresの記事によると、Stringsセクションの下に、文字列のスライスを取得すると元の文字列がメモリに保持されると記載されています。

「(余談ですが、Java やその他の言語には、文字列をスライスして小さな断片を保存するときに、元の文字列への参照によって元の文字列全体がメモリ内に保持されるというよく知られた落とし穴があります。 Go にもこの落とし穴があります。私たちが試みて却下した別の方法は、文字列のスライス (割り当てとコピー) を非常に高価にすることであり、ほとんどのプログラムはそれを避けています。)"

したがって、非常に長い文字列がある場合:

s := "Some very long string..."

そして、小さなスライスを取ります:

newS := s[5:9]

sもリリースするまで、オリジナルはリリースされませんnewSnewSこれを考慮して、長期間保持する必要があるがs、ガベージコレクションのためにリリースする必要がある場合、どのような適切なアプローチをとるべきでしょうか?

たぶんこれだと思いました:

newS := string([]byte(s[5:9]))

しかし、それが実際に機能するかどうか、またはより良い方法があるかどうかはわかりませんでした.

4

2 に答える 2

5

はい、バイトのスライスに変換すると文字列のコピーが作成されるため、元の文字列は参照されなくなり、どこかで GC できます。

これの「証明」として (つまり、バイトのスライスが元の文字列と同じ基になるデータを共有していないことを証明します):

http://play.golang.org/p/pwGrlETibj

編集:バイトのスライスに必要な長さと容量しかないことを証明します(つまり、元の文字列と同じ容量はありません):

http://play.golang.org/p/3pwZtCgtWv

Edit2:メモリプロファイリングで何が起こるかをはっきりと見ることができます。reuseString() では、使用されるメモリは非常に安定しています。copyString() では、[] バイト変換によって行われた文字列のコピーが表示され、急速に大きくなります。

http://play.golang.org/p/kDRjePCkXq

于 2013-01-17T20:55:12.207 に答える
2

文字列をスライスしてスライスを「ライブ」に維持した後、最終的にガベージ コレクションの対象になるようにする適切な方法は、代わりにスライスのコピーを作成し、そのコピーを「ライブ」に維持することです。しかし、現在では、時間パフォーマンスの低下を犠牲にして、より優れたメモリ パフォーマンスを購入しています。どこかで良いかもしれないが、別の場所では悪いかもしれない。場合によっては、推測ではなく適切な測定によってのみ、実際のゲインがどこにあるかがわかります。

たとえば、少し邪悪なものを好むときはStrPackを使用しています ;-)

于 2013-01-17T21:38:15.637 に答える