[解決済み] スライスは値で渡されるのか?
質問
Goで、巡回セールスマン問題のためのスクランブルスライス関数を作ろうとしています。これをやっている間、私は私が与えたスライスを編集し始めたとき、私がそれを渡すたびにスクランブル関数が異なっていることに気づきました。
いくつかのデバッグの後、それは私が関数内のスライスを編集したためであることがわかりました。しかし、Go は "値で渡す" 言語であるはずなので、これはどのようにして可能なのでしょうか?
https://play.golang.org/p/mMivoH0TuV
私が言いたいことを示すために、プレイグラウンドリンクを提供しました。
27 行目を削除すると、それを残した場合とは異なる出力が得られますが、この関数は引数として渡されたときにスライスの独自のコピーを作成することになっているため、違いは生じないはずです。
どなたかこの現象を説明していただけませんか?
どのように解決するのですか?
Goではすべてが値で渡され、スライスもそうです。しかし、スライスの値というのは ヘッダ であり、スライス値には実際に要素が格納されている配列へのポインタのみが含まれます。スライス値にはその要素は含まれません (配列とは異なります)。
そのため、関数にスライスを渡すと、ポインタを含むこのヘッダからコピーが作成され、同じバックアレイを指すことになります。スライスの要素を変更することは、バッキング配列の要素を変更することを意味しますので、同じバッキング配列を共有するすべてのスライスは、その変更を "観察"します。
スライスのヘッダーに何があるのかを確認するために
reflect.SliceHeader
という型があります。
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
関連する/重複する可能性のある質問を参照してください。 Golangの関数パラメータはコピーオンライトで渡されるのでしょうか?
ブログ記事を読む Go スライス: 使用法と内部構造
関連
-
[解決済み] Goで2つのスライスを連結する
-
[解決済み] 2枚のスライスの等価性を確認する
-
[解決済み】PHPの変数は値で渡されるのか、それとも参照で渡されるのか?
-
[解決済み] GoのToString()関数
-
[解決済み] Goでスライスを逆に反復処理する方法はありますか?
-
[解決済み] ユーザーのホームディレクトリを取得する
-
[解決済み] golangにおけるバックティック(``)とダブルクォート("")の違いは何ですか?
-
[解決済み] IntelliJでファイル保存時にgofmtを実行する
-
[解決済み] 構造体のプロパティに名前でアクセスする
-
[解決済み] Go で要件をインストールするにはどうすればよいですか? "パッケージが見つかりません"
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] サーバーでSSLが有効になっていない
-
[解決済み] ゴルーチンの停止方法
-
[解決済み] スライスを宣言するのか、スライスを作るのか?
-
[解決済み] golangでは、マップから値のスライスを取得する良い方法はありますか?
-
[解決済み] go モジュール内のローカルパッケージへのアクセス (go 1.11)
-
[解決済み] チャネルの要素数
-
[解決済み] IntelliJでファイル保存時にgofmtを実行する
-
[解決済み] コンパイルしたファイルのサイズを小さくするには?
-
[解決済み] Go で要件をインストールするにはどうすればよいですか? "パッケージが見つかりません"
-
[解決済み] ソースツリー全体に対するgo fmt