回答

收藏

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

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

有没有办法打印对象的指针(或内部 id,若指针值为 gc 更改)?
9 J2 _' u' p0 o0 a
    6 \' c% N0 [' m
  • 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
    2 J3 d+ B# l. r. b4 F
为什么 go 例程中的指针值显示不同的值?原始对象的数量确实发生了变化,因此可以使用相同的对象。有没有办法检查持久的对象 ID?( C0 Y* o% e6 n) W* B* k5 n
                                                               
* v4 _  i3 T' f% \    解决方案:                                                               
# n% r% M( U8 Y0 L! ^) @# \                                                                Go 函数参数按值传递。
5 R8 X' H. N9 ^. g% @! v; f' `首先,让我们丢弃示例中不相关的部分,这样我们就可以很容易地看到你只是按值传递参数。5 w4 e& {( E- h6 t+ _# E
    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)}
    / p& Y6 f) t5 E$ K: N2 C
输出:
2 ]. Z9 I( N0 ]% ?
    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
    - J9 t$ [1 ~6 n7 F: v  Y# x
在函数中main,i是int内存位置 ( &i)处的变量,0xf i) 42。
3 x( ~6 ^! u3 V$ t6 o在函数中main,p是指向int内存位置 ( &p)变量指针0xf8000000f其值 ( p= &i)0xf800000040指向一个int值 ( *p= i) 42。5 U7 Z3 m/ n, Q- O8 ~# C- o+ Q1 d
在功能main,byval(p)是函数调用,其将值(p= &i)0xf存储位置(自变量)&p)0xf8000000f0给函数byval参数q在存储器位置(&q)0xf8000000d8.换句话说,存储器被分配用于byval参数q和的值main byval的参数p分配给它; 值p和q最初是相同的,但变量p和q是不同的。
4 i! A3 L- H- w1 z, G在功能byval,使用指针q(*int),它是指针的副本p(*int),整数*q(i)被设置为新的int值4143。最后回来指针q设置为nil(零值),这对p因为q副本没有影响。
: z) k' X; X0 O2 Y5 C2 s在函数中main,p是一个指向int内存位置 ( &p)变量指针0xf8000000f其值 ( p= &i)0xf800000040指向一个新int值 ( *p= i) 4143。( u- B! {7 X( Y+ y% g2 q$ j
在函数中main,i是int内存位置 ( &i)处的变量,0xf i) 4143。* ]) l" \: k  {1 M  [
在您的示例中,用作函数调用参数的函数main变量不同于函数参数。它们有相同的名称,但它们有不同的功能域和内存位置。函数参数隐藏了函数调用参数。这就是为什么在我的例子中,我命名参数和参数变量并强调差异。s``gotest``gotest``s``s``s``p``q
/ r  a3 H- B% z" _; Y5 J- ?( &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。
" @. j5 b* l& Q1 N1 K3 [0 N* r0 Q: O- Q你应该接受 mkb 明智建议并停止使用println(&s). 使用fmt包,例如,1 w% @5 v* g: V$ g
    fmt.Printf("%v %p %v\n",&s,s,*s)
    4 L! |4 {- s8 ^9 k5 i+ K
指针指向同一内存位置时具有相同的值;指针指向不同的内存位置时具有不同的值。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则