2020/02/16

[golang]配列はデータまるまる値渡し

前回の続き。

前回はスライスだけだったので、今回は配列をやろう。


01: package main
02: 
03: import "fmt"
04: 
05: func gogo(bababa [5]int) {
06: 	for i := range bababa {
07: 		 bababa[i] = 10 + i
08: 	}
09: }
10: 
11: func lolo(bababa [5]int) {
12: 	i := 3
13: 	for i, bababa[i] = range bababa {
14: 		//break
15: 	}
16: }
17: 
18: func main() {
19: 	var momomo [5]int
20: 
21: 	gogo(momomo)
22: 	lolo(momomo)
23: 	for i, val := range momomo {
24: 		fmt.Printf("[%d] = %d\n", i, val)
25: 	}
26: }
  

$ go run .
[0] = 0
[1] = 0
[2] = 0
[3] = 0
[4] = 0

ほう。

ちなみに、前回のスライスで書いたバージョンはこうだ。

01: package main
02: 
03: import "fmt"
04: 
05: func gogo(bababa []int) {
06: 	for i := range bababa {
07: 		 bababa[i] = 10 + i
08: 	}
09: }
10: 
11: func lolo(bababa []int) {
12: 	i := 3
13: 	for i, bababa[i] = range bababa {
14: 		//break
15: 	}
16: }
17: 
18: func main() {
19: 	var momomo []int
20: 
21: 	momomo = make([]int, 5)
22: 	gogo(momomo)
23: 	lolo(momomo)
24: 	for i, val := range momomo {
25: 		fmt.Printf("[%d] = %d\n", i, val)
26: 	}
27: }
  

$ go run ex3
[0] = 11
[1] = 12
[2] = 10
[3] = 14
[4] = 14

前回は要素数を空欄にしていたので、指定しただけなのだが、それで大きく結果が変わった。

gogo()を呼んでいる内容が反映されていないので、コピー渡しされているのだろうか?


ちょうどよい記事があった。

Golang 関数引数のスライスはポインタで渡すべき? - Qiita
https://qiita.com/ta_ta_ta_miya/items/593ed887f58b251c4fe2

 

golanの関数引数は値渡しらしい。
これはC言語もそうなのだが、配列についてはgolangの方がより値渡しになっているな。

C言語の配列は、配列の変数名だけだとアドレスを返す。
配列の中身は、そのアドレスから始まるメモリに書かれている。
ポインタ変数の場合は、そのアドレスにはポインタが指すアドレスが書かれている。

 

golangでも配列はそのアドレスからデータが書かれているのだろう。だから、配列を「値渡し」すると、そのアドレスに書いてあるデータも含めてコピーされる。
スライスの場合はC言語のポインタ変数みたいなもので、アドレスに書かれているデータがアドレスやサイズのデータなので、それをコピーして渡す。

 

じゃあ、C言語っぽく配列を渡したかったらどうするかというと、スライスにすればいいそうだ。
まあ、この辺は慣れるしかないな。


いかんいかん、ちゃんとスライスにすればOKなのかどうかを確認していなかった。

01: package main
02: 
03: import "fmt"
04: 
05: func gogo(bababa [5]int) {
06: 	for i := range bababa {
07: 		 bababa[i] = 10 + i
08: 	}
09: }
10: 
11: func gogo2(bababa []int) {
12: 	for i := range bababa {
13: 		 bababa[i] = 10 + i
14: 	}
15: }
16: 
17: func main() {
18: 	var momomo [5]int
19: 
20: 	gogo(momomo)
21: 	for i, val := range momomo {
22: 		fmt.Printf("gogo[%d] = %d\n", i, val)
23: 	}
24: 
25: 	gogo2(momomo[:])
26: 	for i, val := range momomo {
27: 		fmt.Printf("gogo2[%d] = %d\n", i, val)
28: 	}
29: }
  

$ go run ex4
gogo[0] = 0
gogo[1] = 0
gogo[2] = 0
gogo[3] = 0
gogo[4] = 0
gogo2[0] = 10
gogo2[1] = 11
gogo2[2] = 12
gogo2[3] = 13
gogo2[4] = 14

うむ、よかろう。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。