2016-10-12 5 views
13

Golangでは、私は旅行セールスマンの問題のためにスクランブルスライス機能を作ろうとしています。これをやりながら、私がスライスを編集し始めたときにスクランブル機能が与えられたことに気がつきました。golangスライスは値渡しですか?

私はデバッグの後、私がその機能のスライスを編集していたことが分かりました。しかし、Golangは「価値渡し」言語であると考えられているので、これはどのように可能ですか?

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

私は私が何を意味するかを示すために遊び場のリンクを提供してきました。 27行目を削除すると、それを残すのとは異なる出力が得られます。これは、関数が引数として渡されたときにスライスの独自のコピーを作成するはずなので、違いはありません。
誰かがこの現象を説明できますか?

答えて

28

はい、Goのすべてが値渡しです。スライスも。しかし、スライス値はヘッダーで、バッキングアレイの連続したセクションが記述されています。スライス値には、実際に要素が格納されている配列へのポインタのみが含まれています。スライスの値には要素が含まれません(配列とは異なります)。

スライスを関数に渡すと、同じバッキング配列を指すポインターを含め、このヘッダーからコピーが作成されます。スライスの要素を変更することは、バッキングアレイの要素を変更することを意味するため、同じバッキングアレイを共有するすべてのスライスは変更を「観察」します。

reflect.SliceHeaderタイプをチェックし、スライスヘッダに何があるかを確認するには:

type SliceHeader struct { 
    Data uintptr 
    Len int 
    Cap int 
} 

関連/可能重複質問を参照してください: Are Golang function parameter passed as copy-on-write?

読むブログ記事:Go Slices: usage and internals

+0

そうするソリューションを関数内のスライスのローカルコピーを作成することです。代わりにそれを編集しますか? – duck

+1

@ user4901806渡されたスライスの要素(それが指しているバッキング配列の要素)を変更しない場合は、コピーを作成します。 – icza

+0

要素を追加すると、元のスライスには追加されません。 – Sahas

関連する問題