Go函数参数按值传递。
首先,让我们丢弃示例中不相关的部分,以便我们可以轻松地看到您只是按值传递参数。例如,
package mainimport "fmt"func byval(q *int) { fmt.Printf("3. byval -- q %T: &q=%p q=&i=%p *q=i=%vn", q, &q, q, *q) *q = 4143 fmt.Printf("4. byval -- q %T: &q=%p q=&i=%p *q=i=%vn", q, &q, q, *q) q = nil}func main() { i := int(42) fmt.Printf("1. main -- i %T: &i=%p i=%vn", i, &i, i) p := &i fmt.Printf("2. main -- p %T: &p=%p p=&i=%p *p=i=%vn", p, &p, p, *p) byval(p) fmt.Printf("5. main -- p %T: &p=%p p=&i=%p *p=i=%vn", p, &p, p, *p) fmt.Printf("6. main -- i %T: &i=%p i=%vn", i, &i, i)}输出:
1. main -- i int: &i=0xf840000040 i=422. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=423. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=424. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=41435. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=41436. 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变量与function
参数不同。它们具有相同的名称,但是是具有不同作用域和存储位置的不同变量。函数参数隐藏函数调用参数。这就是为什么在我的例子,我命名的参数和参数变量,并分别以强调差异。
s``gotest``gotest``s``s``s``p``q
在您的示例中,(
&s)
0x4930d4是
s函数
main中变量的存储位置的地址,用作函数调用的参数
gotest(s,done),并且
0x4974d8是函数
gotest参数的存储位置的地址
s。如果
s =nil在函数末尾设置参数
gotest,则它对
sin中的变量没有影响
main;
sin
main和
sin
gotest是不同的内存位置。就类型而言,
&sis
**Something,
sis
*Something和
*sis
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 %vn", &s, s, *s)当指针指向相同的存储位置时,它们具有相同的值。指针指向不同的内存位置时,它们具有不同的值。



