Go関数の引数は値で渡されます。
まず、例の無関係な部分を破棄して、引数を値で渡しているだけであることが簡単にわかるようにします。例えば、
package main
import "fmt"
func byval(q *int) {
fmt.Printf("3. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
*q = 4143
fmt.Printf("4. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
q = nil
}
func main() {
i := int(42)
fmt.Printf("1. main -- i %T: &i=%p i=%v\n", i, &i, i)
p := &i
fmt.Printf("2. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
byval(p)
fmt.Printf("5. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
fmt.Printf("6. main -- i %T: &i=%p i=%v\n", i, &i, i)
}
出力:
1. main -- i int: &i=0xf840000040 i=42
2. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=42
3. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=42
4. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=4143
5. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=4143
6. main -- i int: &i=0xf840000040 i=4143
関数main
でi
は、は初期値()を持つint
メモリ位置(&i
)の変数です。0xf800000040
i
42
。
機能でmain
、p
へのポインタであるint
メモリ位置に変数(&p
)0xf8000000f0
値(p
= &i
)0xf800000040
にどのポイントint
値(*p
= i
)42
。
関数でmain
、byval(p)
値を代入する関数呼び出しである(p
= &i
)0xf800000040
メモリ位置における引数の(&p
)0xf8000000f0
関数のbyval
パラメータは、q
(メモリ位置&q
)0xf8000000d8
。つまり、byval
パラメータにメモリが割り当てられq
、main
byval
引数の値がパラメータに割り当てられますp
。値p
とq
、最初は同じですが、変数p
とq
別個のものです。
機能ではbyval
、ポインタ使用q
(*int
ポインタのコピーである)、 (p
)、*int
整数*q
(i
)新しいint値に設定されています4143
。最後に戻る前に。ポインタq
はnil
(ゼロ値)に設定されますが、これはコピーであるp
ため影響はありませんq
。
関数main
でp
は、は、新しい値(= )を指す値(= )を持つint
メモリ位置(&p
)の変数へのポインタです。0xf8000000f0
p
&i
0xf800000040
int
*p
i
4143
関数main
でi
は、int
はメモリ位置(&i
)にある変数で0xf800000040
あり、最終値は(i
)4143
です。
あなたの例では、関数呼び出しの引数として使用される関数main
変数は、関数パラメーターと同じではありません。それらは同じ名前ですが、スコープとメモリ位置が異なる異なる変数です。関数パラメーターは、関数呼び出し引数を非表示にします。そのため、私の例では、違いを強調するために、引数変数とパラメーター変数にそれぞれ名前を付けました。s
gotest
gotest
s
s
s
p
q
あなたの例では、( &s
)0x4930d4
変数のメモリ位置のアドレスであるs
関数でmain
関数呼び出しの引数として使用されgotest(s, done)
、そして0x4974d8
機能のためのメモリ位置のアドレスであるgotest
パラメータs
。s = nil
関数の最後にパラメーターを設定gotest
した場合s
、main
;の変数には影響しません。s
inmain
とs
ingotest
は、異なるメモリ位置です。種類の面では、&s
あり**Something
、s
あり*Something
、そして*s
ありますSomething
。&s
(メモリ位置のアドレス)s
へのポインタであり、タイプの匿名変数(メモリ位置のアドレス)へのポインタです。Something
。値の面では、main.&s != gotest.&s
、main.s == gotest.s
、main.*s == gotest.*s
、とmain.s.number == gotest.s.number
。
mkbの賢明なアドバイスを受けて、の使用をやめる必要がありprintln(&s)
ます。fmt
たとえば、パッケージを使用します。
fmt.Printf("%v %p %v\n", &s, s, *s)
同じメモリ位置を指す場合、ポインタの値は同じです。ポインタが異なるメモリ位置を指す場合、ポインタの値は異なります。