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)の変数です。0xf800000040i42。
機能で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)の変数へのポインタです。0xf8000000f0p&i0xf800000040int*pi4143
関数mainでiは、intはメモリ位置(&i)にある変数で0xf800000040あり、最終値は(i)4143です。
あなたの例では、関数呼び出しの引数として使用される関数main変数は、関数パラメーターと同じではありません。それらは同じ名前ですが、スコープとメモリ位置が異なる異なる変数です。関数パラメーターは、関数呼び出し引数を非表示にします。そのため、私の例では、違いを強調するために、引数変数とパラメーター変数にそれぞれ名前を付けました。sgotestgotestssspq
あなたの例では、( &s)0x4930d4変数のメモリ位置のアドレスであるs関数でmain関数呼び出しの引数として使用されgotest(s, done)、そして0x4974d8機能のためのメモリ位置のアドレスであるgotestパラメータs。s = nil関数の最後にパラメーターを設定gotestした場合s、main;の変数には影響しません。sinmainとsingotestは、異なるメモリ位置です。種類の面では、&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)
同じメモリ位置を指す場合、ポインタの値は同じです。ポインタが異なるメモリ位置を指す場合、ポインタの値は異なります。