2016-05-17 18 views
1

2次元のスライスを使用して複数の線を表現していますが、線の1つに追加すると非常に奇妙な動作をします。私はこのプログラムの出力は2dスライスに追加するときの奇妙な動作

Before: 
first line 
second line 
third line 

After: 
first line-inserted text- 
second line 
third line 

ことを期待する

package main 

import (
    "bytes" 
    "fmt" 
) 

func main() { 
    str := []byte("first line\nsecond line\nthird line") 
    values := bytes.Split(str, []byte("\n")) 

    fmt.Println("Before:") 
    fmt.Println(string(values[0])) 
    fmt.Println(string(values[1])) 
    fmt.Println(string(values[2])) 
    fmt.Println() 

    values[0] = append(values[0], []byte("-inserted text-")...) 

    fmt.Println("After:") 
    fmt.Println(string(values[0])) 
    fmt.Println(string(values[1])) 
    fmt.Println(string(values[2])) 
} 

しかし、その代わりに出力されます:ここで

は一例です

Before: 
first line 
second line 
third line 

After: 
first line-inserted text- 
inserted te 
t-ird line 

https://play.golang.org/p/iNw6s1S66U

なぜこれが起こっていて、どうすれば修正できますか?

興味深いことに、これは私がスプリットを使用して、代わりにそのような値を定義しない場合は発生しません:

values := [][]byte{[]byte("first line"), []byte("second line"), []byte("third line")} 

https://play.golang.org/p/pEflrhKLd4

答えて

2

基本ストレージは共有されているため、必要な効果を得るには、返されたスライスだけでなく、bytes.Splitから返されたスライスのコピーを保存する必要があります。返された最初のスライスに追加すると、基本的に次のスライス全体でストンプします。

+0

ストレージが共有されているとはどういう意味ですか?スライスの要素を連続して指していますか? – AJPennster

+0

「str」はバイトスライスで、ある程度のバックエンドストレージを持ちます。次に、 'byte.Slice'は[byte]のスライスを返します。これらのスライスはすべて同じバッキングストレージを指しています。だから彼らはすべて(最初は)同じ共有ストレージを指しています。 – Vatine

+0

私はそれを確認することができた。 – AJPennster

1

文字列に追加されたあなたがやっているのではなく、配列に追加し、そのスライスの基礎となるデータ構造をオーバーフローさせます。これは、配列の残りの部分が追加している文字列で上書きされる理由です。明確にするため

(これは必ずしもそうではないかもしれない):

アレイvaluesが連続並ん3 []バイト・ブロックから構成されています。それぞれの[]バイトブロックは、(その中にある文字列の長さに基づいて)固定長を持ちます。したがって、values[0]の長さは10です( '\ n'または '\ 0'を除く)。今度はそのブロックに"-inserted text-"を追加しようとすると、文字はvalues[1]の文字に置き換えられ、values[1]の文字は"-inserted text-"の文字に置き換えられます。そのため、values[1]values[1]の文字の一部が表示されます。

関連する問題