Given the following golang code:
type Pointer struct { x, y int }
func foo(p *Pointer) *int {
return &p.y
}
CompilerExplorer shows that return &p.y compiles to
TESTB AL, (AX)
ADDQ $8, AX
RET
It's easy to understand. TESTB is a null check, then ADDQ produce a pointer to p.y by adding offset of Pointer::y to p.
What I don't understand is, given a pointer to p.y, how does the garbage collector knows it's not just an arbitrary *int, but a pointer to a Pointer::y, so p must remain alive as long as a pointer to p.y is still alive?