2016-11-09 13 views
1

ほとんどの言語(C++など)で渡す配列は暗黙的に参照渡しになるため、関数内の渡された配列を変更すると元のものに変更されます。私はGolangとAlan A.Aの "The Go Programming Language"という本を学んでいます。 DonovanとBrian W. Kernighanそれは、その振る舞いが他の言語とは異なると言われています - 暗黙のうちに配列を参照渡しに渡すわけではありません。Golangが配列を関数に渡してそれを変更する

私はちょっと混乱しています。つまり、参照なしで配列を渡しても配列自体は変更されないはずですか?私はそれを説明してみましょう:配列上記のコードで

func main() { 
    tab := []int{1, 2, 3} 
    fmt.Println(tab) 
    // Results in [1 2 3] 
    reverse(tab) 
    fmt.Println(tab) 
    // Results in [3 2 1] 
} 

func reverse(tab []int) { 
    for i, j := 0, len(tab)-1; i < j; i, j = i+1, j-1 { 
     tab[i], tab[j] = tab[j], tab[i] 
    } 
} 

は参照によって渡されていないが、逆関数は、元の1を修正するので、それはややだろうC++プログラムのように動作します。誰でも私にその違いを説明できますか?

PS:申し訳ありませんがダミー質問ですが、私はGolangに全く新しく、基本をよく理解しようとしています。

+2

あなたは(https://golang.org/doc/effective_go.html#slices)、[ "ツアー[「有効ゴー」のスライスセクション]のように、ドキュメントのいずれかを介して行っています(https://tour.golang.org/moretypes/7)、[スライスの仕様](https://golang.org/ref/spec#Slice_types)、または[Go blogスライスについての投稿](https://blog.golang.org/go-slices-usage-and-internals)? – JimB

答えて

4

説明はかなり単純です。arrayは、のコードで明示的に宣言または使用されていません。 tabローカル変数とtabパラメータはslicesです。

In Goは、配列の長さがタイプの一部です(例: [3]int(これは、例えば[2]intおよび[3]intが2つの異なる/別個のアレイタイプであることに相当する)。長さが存在しない場合(明示的に[2]intまたはcomposite literal[...]int{1, 2, 3}のように)、配列型ではなくスライス型です。

はい、読んでいると、配列値はすべての要素を意味し、渡された(または割り当てられた)とき、その要素はすべてコピーされます。ただし、スライスは配列の連続したセクションを記述する小さな記述子、ヘッダーです。スライスが渡される(または割り当てられる)とき、このヘッダのみがコピーされ(ポインタが含まれています)、同じ基本配列を指します。したがって、スライスコピーの要素を変更すると、その要素を保持するバッキングアレイが1つしかないので、変更は元のスライスに反映されます。あなたは正確にスライスヘッダに何があるかを知りたい場合は

、あなたはreflect.SliceHeaderタイプをチェックアウトすることがあります。それは、スライスの最初の要素へのポインタ、長さ、スライスの容量を含むstructです。

偉大な詳細にこれを説明する以下のブログ記事をお読みください:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

また詳細は、これらの関連の質問を参照してください。

Why have arrays in Go?

Are golang slices pass by value?

1

定義しているのは、ではなく、の配列で、golangのマニュアルで指定されているとおりに渡されます。 thisリンクを確認してください。

関連する問題