如何打印 Go 对象的指针值? 指针值是什么意思?

我只是在玩围棋,对于何时通过值或引用传递结构还没有一个很好的心理模型。

这可能是一个非常愚蠢的问题,但我只是想试验一下,看看我是否仍然在同一个对象上工作,或者我已经制作了一个副本(通过值传递)。

是否有办法打印对象的指针(或内部 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)
}

给我的窗口(8g 编译版本) :

0x4930d4
from gotest:
0x4974d8
42
0x4930d4
42

为什么 go 例程中的指针值显示不同的值?原始物体上的数量确实被改变了,所以它是用同一个物体工作的。有没有一种方法可以查看持久化的对象 id?

126723 次浏览
type sometype struct { }
a := sometype {}
b := int(2)
println("Ptr to a", &a)
println("Ptr to b", &b)

In Go, arguments are passed by value.

package main


import "fmt"


type SomeStruct struct {
e int
}


// struct passed by value
func v(v SomeStruct) {
fmt.Printf("v: %p %v\n", &v, v)
v.e = 2
fmt.Printf("v: %p %v\n", &v, v)
}


// pointer to struct passed by value
func p(p *SomeStruct) {
fmt.Printf("p: %p %v\n", p, *p)
p.e = 2
fmt.Printf("p: %p %v\n", p, *p)
}


func main() {
var s SomeStruct
s.e = 1
fmt.Printf("s: %p %v\n", &s, s)
v(s)
fmt.Printf("s: %p %v\n", &s, s)
p(&s)
fmt.Printf("s: %p %v\n", &s, s)
}

Output:

s: 0xf800000040 {1}
v: 0xf8000000e0 {1}
v: 0xf8000000e0 {2}
s: 0xf800000040 {1}
p: 0xf800000040 {1}
p: 0xf800000040 {2}
s: 0xf800000040 {2}

Go function arguments are passed by value.

First, let's discard the irrelevant parts of your example, so that we can easily see that you are merely passing an argument by value. For example,

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)
}

Output:

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

In function main, i is an int variable at memory location (&i) 0xf800000040 with an initial value (i) 42.

In function main, p is a pointer to an int variable at memory location (&p) 0xf8000000f0 with a value (p=&i) 0xf800000040 which points to an int value (*p=p0) p1.

In function main, byval(p) is a function call which assigns the value (p=&i) 0xf800000040 of the argument at memory location (&p) 0xf8000000f0 to the function byval parameter q at memory location (&q) byval(p)0. In other words, memory is allocated for the byval parameter q and the value of the main byval argument p is assigned to it; the values of p and q are initially the same, but the variables p and q are distinct.

In function byval, using pointer q (*int), which is a copy of pointer p (*int), integer *q (i) is set to a new int value 4143. At the end before returning. the pointer q is set to nil (zero value), which has no effect on p since q is a copy.

In function main, p is a pointer to an int variable at memory location (&p) 0xf8000000f0 with a value (p=&i) 0xf800000040 which points to a new int value (*p=p0) p1.

In function main, i is an int variable at memory location (&i) 0xf800000040 with a final value (i) 4143.

In your example, the function main variable s used as an argument to the function gotest call is not the same as the function gotest parameter s. They have the same name, but are different variables with different scopes and memory locations. The function parameter s hides the function call argument s. That's why in my example, I named the argument and parameter variables p and q respectively to emphasize the difference.

In your example, (&s) 0x4930d4 is the address of the memory location for the variable s in function main that is used as an argument to the function call gotest(s, done), and 0x4974d8 is the address of the memory location for the function gotest parameter s. If you set parameter s = nil at the end of function gotest, it has no effect on variable s in main; s in main and s in gotest are distinct memory locations. In terms of types, &s is 0x4930d47, s is 0x4930d49, and s0 is s1. &s is a pointer to (address of memory location) s, which is a pointer to (address of memory location) an anonymous variable of type s1. In terms of values, s5, s6, s7, and s8.

You should take mkb's sage advice and stop using println(&s). Use the fmt package, for example,

fmt.Printf("%v %p %v\n", &s, s, *s)

Pointers have the same value when they point to the same memory location; pointers have different values when they point to different memory locations.

package main


import "fmt"


func zeroval(ival int) {
ival = 0
}


func zeroptr(iptr *int) {
*iptr = 0
}


func main() {
i := 1
fmt.Println("initial:", i)
zeroval(i)
fmt.Println("zeroval:", i)
//The &i syntax gives the memory address of i, i.e. a pointer to i.
zeroptr(&i)
fmt.Println("zeroptr:", i)
//Pointers can be printed too.
fmt.Println("pointer:", &i)
}

OUTPUT:

$ go run pointers.go
initial: 1
zeroval: 1
zeroptr: 0
pointer: 0x42131100

How do I print the pointer value of a Go object?

package main


import (
"fmt"
)


func main() {
a := 42
fmt.Println(&a)
}

results in:

0x1040a124

What does the pointer value mean?

According to Wikipedia:

A pointer references a location in memory