Go の文字列は不変ですが、その参照を保持する変数は不変ではありません。したがって、マルチスレッド環境で文字列を操作する場合は、文字列自体ではなく文字列変数へのアクセスを同期する必要があります。
文字列がアトミックに型付けされない理由
アトミック型は、初期化後にその値が決して変更されないことを保証します。ただし、文字列変数は再割り当てできるため、文字列はアトミックに型付けされません。
文字列変数の同期
複数のスレッドが文字列変数にアクセスする場合は常に同期が必要です。少なくとも 1 回のアクセスは書き込みです。これは、文字列の値は、文字列自体を変更することではなく、変数を再割り当てすることによってのみ変更できるためです。
実際
文字列値「hello」がある場合」の場合、変数に新しい値を割り当てないと仮定すると、無期限に「hello」のままになります。ただし、スライス値 []byte{1, 2, 3} がある場合、スライスが値によって渡される場合でも、その要素は同時に変更できます。
次の例を考えてみましょう:
var sig = make(chan int) func main() { s := []byte{1, 2, 3} go func() { <-sig s[0] = 100 sig <- 0 }() sliceTest(s) } func sliceTest(s []byte) { fmt.Println("First s =", s) sig <- 0 // send signal to modify now <-sig // Wait for modification to complete fmt.Println("Second s =", s) }
出力:
First s = [1 2 3] Second s = [100 2 3]
この例では、sliceTest() はスライスを受け取り、その初期値を出力します。次に、別の goroutine がスライスを変更するのを待ってから、その変更された値を出力します。これは、スライス値を同時に変更できることを示しています。ただし、sliceTest() が文字列引数を受け取った場合、この変更は行われません。
以上が文字列は不変であるにもかかわらず、Go で文字列変数へのアクセスを同期する必要があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。