指针变量何时更改其地址?

Consider the following example and notice how the location of pointer variable a remains fixed, as expected:

var a *int

v1 := 1
v2 := 2

a = &v1
fmt.Printf("%p
", &a) // output: 0x1040c128
a = &v2
fmt.Printf("%p
", &a) // output: 0x1040c128

Now consider the following struct definition:

type foo struct {
    bar int
}

If a is declared as a pointer variable to foo as in this example, its location in memory does not remain fixed.

var a *foo

v1 := foo{bar: 1}
v2 := foo{bar: 2}

a = &v1
fmt.Printf("%p
", a) // output: 0x10414020
a = &v2
fmt.Printf("%p
", a) // output: 0x10414024

Why is that?

Are you sure you just didn't make a typo and used fmt.Printf("%p ", a) instead of fmt.Printf("%p ", &a) because the first one uses &a and your second example uses a.

Long answer:

With

fmt.Printf("%p
", a)

you're printing out the value of a which is of type *foo which is a pointer. Roughly speaking a pointer is a variable holding an address of a memory location. With

 a = &v1

you set a to the address of v1

 a = &v2

you set a to the address of v2. v1 and v2 have different locations in memory and thus you when you print the value of a you'll see exactly that.

If you use

var a *foo

v1 := foo{bar: 1}
v2 := foo{bar: 2}

a = &v1
fmt.Printf("%p
", &a)
a = &v2
fmt.Printf("%p
", &a)

then you'll see the same number printed twice because now you're printing out the location of a. So:

a = &v
fmt.Printf("%p
", a) // prints location of v, not location of a

a = &v
fmt.Printf("%p
", &a) // prints location of a, not location of v

Remark:

There's some ambiguity as to what people call a pointer and what an address. Some say that a pointer is an address because it contains an "address of a memory location" but a pointer is not actually a memory address depending on the exact context. Also, a points to b usually means that a is a pointer containing the address of b. Likewise, &v is either referred to as "the address of v" and "a pointer to v" which (at least in my opinion) are equally correct which is why I originally used "set a to a pointer to v".