回答

收藏

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

技术问答 技术问答 237 人阅读 | 0 人回复 | 2023-09-12

有没有办法打印对象的指针(或内部 id,若指针值为 gc 更改)?7 r  E6 G2 i$ v8 A
    6 z" {$ o+ M1 a( z, h
  • package mainimport ( "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 在我的 Windows 上给出(8g 编译版本):[code]0x4930d4from gotest:0x4974d8420x4930d442
    , j8 b. L7 r$ F! d5 z: e) c# g' Q
为什么 go 例程中的指针值显示不同的值?原始对象的数量确实发生了变化,因此可以使用相同的对象。有没有办法检查持久的对象 ID?
+ c) k9 P9 s* R                                                               
5 h4 h3 P$ ~  M    解决方案:                                                               
, R) y: f5 o5 o                                                                Go 函数参数按值传递。6 g% m7 [2 K8 r& f+ R
首先,让我们丢弃示例中不相关的部分,这样我们就可以很容易地看到你只是按值传递参数。
3 P; L4 y5 Y4 H. M% q
    package mainimport "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)}/ j8 r/ X8 V6 ]0 L2 V7 K5 W3 N% U
输出:1 u$ w- {# T* P2 [+ [0 D4 p' 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
    / |3 ?- I% y1 U
在函数中main,i是int内存位置 ( &i)处的变量,0xf i) 42。
* a' w% m7 V  Y9 x6 L在函数中main,p是指向int内存位置 ( &p)变量指针0xf8000000f其值 ( p= &i)0xf800000040指向一个int值 ( *p= i) 42。; a& {+ g: n+ a8 y0 T
在功能main,byval(p)是函数调用,其将值(p= &i)0xf存储位置(自变量)&p)0xf8000000f0给函数byval参数q在存储器位置(&q)0xf8000000d8.换句话说,存储器被分配用于byval参数q和的值main byval的参数p分配给它; 值p和q最初是相同的,但变量p和q是不同的。( _6 J0 ]/ K0 M* ~, d& w8 w
在功能byval,使用指针q(*int),它是指针的副本p(*int),整数*q(i)被设置为新的int值4143。最后回来指针q设置为nil(零值),这对p因为q副本没有影响。- C. \6 m" `8 I2 R& x
在函数中main,p是一个指向int内存位置 ( &p)变量指针0xf8000000f其值 ( p= &i)0xf800000040指向一个新int值 ( *p= i) 4143。+ b3 N2 A$ L8 ?8 R! W! r* O! n
在函数中main,i是int内存位置 ( &i)处的变量,0xf i) 4143。
% v# v( p4 m, w( s9 J$ P' C* q; v在您的示例中,用作函数调用参数的函数main变量不同于函数参数。它们有相同的名称,但它们有不同的功能域和内存位置。函数参数隐藏了函数调用参数。这就是为什么在我的例子中,我命名参数和参数变量并强调差异。s``gotest``gotest``s``s``s``p``q
/ ?6 Q! {( Z# ^) V, ^( &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。
+ I2 X$ z1 i& R2 z  ]你应该接受 mkb 明智建议并停止使用println(&s). 使用fmt包,例如,
" y9 m" x: |" r3 f
    fmt.Printf("%v %p %v\n",&s,s,*s)
    # T/ x1 A# |$ ~2 C! C8 B
指针指向同一内存位置时具有相同的值;指针指向不同的内存位置时具有不同的值。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则