Skip to content

Commit 6503d89

Browse files
authored
Merge pull request #708 from devlights:add-everything-in-a-copy-example
Add everything_in_a_copy example
2 parents 7e4e535 + b419a66 commit 6503d89

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: run
9+
run:
10+
cmds:
11+
- go run .
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"github.com/devlights/gomy/output"
5+
)
6+
7+
func main() {
8+
if err := run(); err != nil {
9+
panic(err)
10+
}
11+
}
12+
13+
func run() error {
14+
//
15+
// Goにおける代入は「全てコピー」となる.
16+
// - 構造体を返す関数の結果を代入すると、その「構造体のコピー」が行われる.
17+
// - ポインタを返す関数の結果を代入すると、その「メモリアドレスのコピー」が行われる.
18+
// - 構造体を受け取る関数に、構造体を渡すと、その「構造体のコピー」が行われる.
19+
// - ポインタを受け取る関数に、ポインタを渡すと、その「メモリアドレスのコピー」が行われる.
20+
//
21+
// Goの for range の挙動も同じ理屈で動いている.
22+
//
23+
24+
// 構造体を返す関数の結果を代入すると、その「構造体のコピー」が行われる
25+
v1 := NewValueType(100)
26+
27+
// ポインタを返す関数の結果を代入すると、「メモリアドレスのコピー」が行われる
28+
v2 := NewPointerType(100)
29+
30+
v1.Change() // レシーバーにはコピーが渡されるので内部で値を変えても元は変わっていない
31+
v2.Change() // レジーバーにはメモリアドレスのコピーが渡されるので値を変えると元も変わる
32+
33+
output.Stdoutf("[v1]", "%v\n", v1)
34+
output.Stdoutf("[v2]", "%v\n", v2)
35+
36+
// for range 文は、for i, v := range xx と記述するので、代入が行われる(:=の存在).
37+
// range は、対象のオブジェクトをコピーしてからループを始める.
38+
// この際のコピーのルールは上記の理屈となる.
39+
//
40+
// また、ループ変数にはループが始まる直前に一つの変数が確保され
41+
// その変数に繰り返しループごとの値が代入される.
42+
// (つまり、ループ変数のアドレスを取ると全部同じアドレス)
43+
//
44+
// この場合も代入が発生しているので同じ理屈となる
45+
// (この同じ変数に繰り返し代入される挙動は Go 1.22 で変わる予定 (GOEXPERIMENT loopvar))
46+
v3 := []interface{ Change() }{
47+
NewValueType(1), NewValueType(2), NewValueType(3),
48+
NewPointerType(1), NewPointerType(2), NewPointerType(3),
49+
}
50+
51+
for _, v := range v3 {
52+
v.Change()
53+
}
54+
55+
output.Stdoutf("[v3]", "%v\n", v3)
56+
57+
return nil
58+
59+
/*
60+
$ task
61+
task: [run] go run .
62+
[v1] 100
63+
[v2] 200
64+
[v3] [1 2 3 101 102 103]
65+
*/
66+
67+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import "fmt"
4+
5+
type ValueType struct {
6+
Value int
7+
}
8+
9+
type PointerType struct {
10+
Value int
11+
}
12+
13+
func NewValueType(v int) ValueType {
14+
o := ValueType{Value: v}
15+
return o
16+
}
17+
18+
func NewPointerType(v int) *PointerType {
19+
o := &PointerType{Value: v}
20+
return o
21+
}
22+
23+
func (me ValueType) Change() {
24+
me.Value += 100 //lint:ignore SA4005 It's ok because this is just a example.
25+
}
26+
27+
func (me *PointerType) Change() {
28+
me.Value += 100
29+
}
30+
31+
func (me ValueType) String() string {
32+
return fmt.Sprint(me.Value)
33+
}
34+
35+
func (me *PointerType) String() string {
36+
return fmt.Sprint(me.Value)
37+
}

0 commit comments

Comments
 (0)