有没有办法打印对象的指针(或内部 id,如果指针值被 gc 更改)?
package main import ( "runtime" ) type Something struct { number int queue chan int } func gotest( s *Something, done chan bool ) { println( "from gotest:") println( &s ) for num := range s.queue { println( num ) s.number = num } done <- true } func main() { runtime.GOMAXPROCS(4) s := new(Something) println(&s) s.queue = make(chan int) done := make(chan bool) go gotest(s, done) s.queue <- 42 close(s.queue) <- done println(&s) println(s.number) }
在我的 Windows 上给出(8g 编译版本):
0x4930d4 from gotest: 0x4974d8 42 0x4930d4 42
为什么 go 例程中的指针值显示不同的值?原始对象上的数量确实发生了变化,因此它可以使用相同的对象。有没有办法查看持久的对象 ID?
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
i
int
&i
0xf800000040
42
在函数中main,p是指向int内存位置 ( &p)处的变量的指针0xf8000000f0,其值 ( p= &i)0xf800000040指向一个int值 ( *p= i) 42。
p
&p
0xf8000000f0
*p
在功能main,byval(p)是一个函数调用,其将值(p= &i)0xf800000040在存储器位置(自变量的&p)0xf8000000f0给函数byval参数q在存储器位置(&q)0xf8000000d8。换句话说,存储器被分配用于byval参数q和的值main byval的参数p被分配给它; 的值p和q最初是相同的,但变量p和q是不同的。
byval(p)
byval
q
&q
0xf8000000d8
在功能byval,使用指针q(*int),它是指针的一个拷贝p(*int),整数*q(i)被设置为一个新的int值4143。最后回来之前。指针q设置为nil(零值),这对p因为q是副本没有影响。
*int
*q
4143
nil
在函数中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``gotest``gotest``s``s``s``p``q
在您的示例中, ( &s)0x4930d4是s函数main中用作函数调用参数的变量的内存位置地址gotest(s, done),并且0x4974d8是函数gotest参数的内存位置地址s。如果s = nil在函数末尾设置参数gotest,则对变量sin没有影响main;sinmain和singotest是不同的内存位置。在类型方面,&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。
&s
0x4930d4
s
gotest(s, done)
0x4974d8
gotest
s = nil
**Something
*Something
*s
Something
main.&s != gotest.&s
main.s == gotest.s
main.*s == gotest.*s
main.s.number == gotest.s.number
您应该接受 mkb 的明智建议并停止使用println(&s). 使用fmt包,例如,
println(&s)
fmt
fmt.Printf("%v %p %v\n", &s, s, *s)
指针指向同一内存位置时具有相同的值;指针指向不同的内存位置时具有不同的值。