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

时间:2011-02-08 21:22:37

标签: go

我只是在玩Go,并且还没有一个很好的心理模型,可以通过值或参考传递结构。

这可能是一个非常愚蠢的问题,但我只是想稍微试验一下,看看我是否还在处理同一个对象,或者我已经复制了它(通过值传递它)。

有没有办法打印对象的指针(如果指针值被gc改变,则为内部id)?

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?

5 个答案:

答案 0 :(得分:75)

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变量&i0xf800000040,其初始值为i42

在函数main中,p是指向内存位置int&p的{​​{1}}变量的指针,其值为0xf8000000f0 } = p&i指向0xf800000040值(int = *pi

在函数42中,main是一个函数调用,它在内存位置分配参数的值(byval(p) = p&i({ {1}})0xf800000040到内存位置(&p0xf8000000f0的函数byval参数q。换句话说,为&q参数0xf8000000d8分配了内存,并为其分配了byval q参数main的值; byvalp的值最初相同,但变量pq是不同的。

在函数p中,使用指针qbyval),它是指针q*int)的副本,整数{{1} }(p)设置为新的int值*int。在返回之前结束。指针*q设置为i(零值),这对4143没有影响,因为q是副本。

在函数nil中,p是指向内存位置qmain的{​​{1}}变量的指针,其值为p } = int&p指向新的0xf8000000f0值(p = &i0xf800000040

在功能int中,*p是内存位置的i变量(4143main,其最终值为iint

在您的示例中,用作函数&i调用的参数的函数0xf800000040变量i与函数4143参数{{1}不同}。它们具有相同的名称,但是具有不同范围和内存位置的不同变量。函数参数main隐藏函数调用参数s。这就是为什么在我的例子中,我分别命名参数和参数变量gotestgotest来强调差异。

在您的示例中,(ss是函数s中变量p的内存位置的地址,用作函数的参数致电q&s是函数0x4930d4参数s的内存位置地址。如果您在函数main的末尾设置参数gotest(s, done),则它对0x4974d8中的变量gotest没有影响; s中的s = nilgotest中的s是不同的记忆位置。就类型而言,mainsmainsgotest&s**Something是指向(内存位置的地址)s的指针,它是指向({1}}类型的匿名变量的指针(内存位置的地址)。就价值而言,*Something*sSomething&s

你应该接受mkb的sage建议并停止使用s。使用Something包,例如

main.&s != gotest.&s

当指针指向相同的内存位置时,指针具有相同的值;当指针指向不同的内存位置时,它们具有不同的值。

答案 1 :(得分:5)

在Go中,参数按值传递。

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

输出:

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

输出:

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

答案 4 :(得分:0)

  

我如何print Go对象的指针值?

package main

import (
    "fmt"
)

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

结果:

0x1040a124
  

指针值是什么意思?

根据Wikipedia

  

指针引用内存中的位置