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

后端 未结 5 1365
野的像风
野的像风 2020-12-12 11:24

I am just playing around with Go and do not yet have a good mental model of when structs are passed by value or by reference.

This may be a very dumb question but I

相关标签:
5条回答
  • 2020-12-12 12:04
    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
    
    0 讨论(0)
  • 2020-12-12 12:13

    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

    0 讨论(0)
  • 2020-12-12 12:15

    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}
    
    0 讨论(0)
  • 2020-12-12 12:28

    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=i) 42.

    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) 0xf8000000d8. 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=i) 4143.

    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 **Something, s is *Something, and *s is Something. &s is a pointer to (address of memory location) s, which is a pointer to (address of memory location) an anonymous variable of type Something. In terms of values, main.&s != gotest.&s, main.s == gotest.s, main.*s == gotest.*s, and main.s.number == gotest.s.number.

    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.

    0 讨论(0)
  • 2020-12-12 12:30
    type sometype struct { }
    a := sometype {}
    b := int(2)
    println("Ptr to a", &a)
    println("Ptr to b", &b)
    
    0 讨论(0)
提交回复
热议问题