文字列のスライスを文字列へのポインタのスライスに変換する
プログラミングでは、文字列値のスライスをスライスに変換する必要がある場合があります。文字列へのポインタの。参照とメモリ割り当ての微妙な違いを扱う場合、これは難しい場合があります。
元の問題
次の例を考えてみましょう。
package main import ( "fmt" ) func main() { values1 := []string{"a", "b", "c"} var values2 []*string for _, v := range values1 { fmt.Printf("%p | %T\n", v, v) values2 = append(values2, &v) } fmt.Println(values2) }
Inこの例では、values1 の文字列要素を指すポインターのスライス (values2) を作成することを想定しています。ただし、出力では、すべてのポインターが同じアドレスを指していることが明らかになり、個別の文字列ではなく同じオブジェクトを参照していることがわかります。
%!p(string=a) => string %!p(string=b) => string %!p(string=c) => string [0xc42000e1d0 0xc42000e1d0 0xc42000e1d0]
問題の理解
この現象は、ループ変数 v が値によって渡されるために発生します。各反復で、values1 内の現在の文字列のコピーを受け取るため、values2 に追加されたすべてのポインターは、文字列の同じコピーを指します。
提案されたソリューション
この問題を解決するには、values1 の文字列要素へのポインタをループ変数に渡す必要があります。 1 つの解決策は、次のアプローチを使用することです。
for i, _ := range values1 { values2 = append(values2, &values1[i]) }
ここでは、ループ変数 i を使用して value1 にインデックスを付け、インデックス付き要素のアドレスが value2 に追加されます。これにより、values2 の各ポインターが、values1 内の固有の文字列要素を指すようになります。
メモリ管理への影響
上記の解決策ではポインターが解決されることに注意することが重要です。この問題はメモリ管理に影響を及ぼします。スライスvalues2にはvalues1の要素へのポインタが含まれており、values1とvalues2の両方が到達不能になるまでvalues1がガベージコレクションされるのを防ぎます。さらに、value1 の要素を変更すると、value2 の要素は両方とも同じデータを指しているため、間接的に変更されます。
代替ソリューション
メモリ管理への影響を回避する別のソリューション一時的なローカル変数を作成し、それらのアドレスを value2:
for _, v := range values1 { v2 := v values2 = append(values2, &v2) }
に追加することです。このアプローチでは、それぞれ反復により、新しいローカル変数 v2 が作成され、values1 の現在の文字列の値が割り当てられます。次に、v2 のアドレスが value2 に追加されます。これにより、values2 の各ポインターが独立した文字列オブジェクトを指すようになり、values1 は value2 とは独立してガベージ コレクションできるようになります。
以上がGoで文字列のスライスを文字列ポインタのスライスに正しく変換するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。