次のコードの出力は?
func test1(x int) (func(), func()) {
return func() {
fmt.Println(x)
x += 10
}, func() {
fmt.Println(x)
}
}
func test2(x []int) (func(), func()) {
return func() {
fmt.Println(x)
x[0] = 0
}, func() {
fmt.Println(x)
}
}
func test3(x [3]int) (func(), func()) {
return func() {
fmt.Println(x)
x[0] = 0
}, func() {
fmt.Println(x)
}
}
func main() {
cc := 10
dd :=[]int{1,2,3}
a,b := test1(cc)
a()
b()
fmt.Println(c)
c,d := test2(dd)
c()
d()
fmt.Println(dd)
ee := [3]{4,5,6}
e,f := test3(ee)
e()
f()
fmt.Println(ee)
}
結果
a()==> 10
b()==> 20
cc ==>10
c() ==> [1 2 3]
d() ==> [0 2 3]
dd ==>[0 2 3]
e()==>[4 5 6]
f()==>[0 5 6]
ee ==>[4 5 6]
まとめ
配列と整数は値型であり、関数に参照を渡すとそのコピーがコピーされ、そのコピーは新しくオープンされたメモリアドレスとなり、関数内部で変更しても元の値に影響を与えません。一方、スライス・スライス型は参照型であり、渡される参照はポインタなので、関数内部で変更すると元の値が変わってしまいます。
補足:延期を伴う複合試験
func test(x [3]int) (func(), func()) {
defer func() {x[2]=1}()
return func() {
fmt.Printf("%T,%v
",x,x)
x[0] = 0
}, func() {
fmt.Printf("%T,%v
",x,x)
}
}
func main() {
var c =[3]int{1,2,3}
a, b := test(c)
a()
b()
fmt.Printf("%T,%v
",c,c)
}
輸出
[3]int,[1 2 1]
[3]int,[0 2 1]
[3]int,[1 2 3]