Go语言中结构体使用&符号的原因及与普通结构体的差异
Great question! Let's break down the key differences and why you'd choose one over the other, using your example code as context.
Core Differences
Memory Handling & Copy Behavior
- A plain
Vertexis a value type: when you assign it to another variable or pass it to a function, Go creates a full copy of the entire struct. So if you dovCopy := v1,vCopyis a separate instance—changes tovCopy.Xwon't affectv1.X. *Vertexis a pointer type: it stores the memory address of aVertexinstance instead of the struct data itself. Assigning or passing a pointer only copies the address (8 bytes on 64-bit systems), not the whole struct. SopCopy := pmeans bothpandpCopypoint to the same underlyingVertexinstance.
- A plain
Mutability & Modification
- To modify a plain struct's fields, you either modify the instance directly, or if it's passed to a function, you have to return the modified struct and reassign it (since the function gets a copy). For example:
func updateVertex(v Vertex) Vertex { v.X = 10 return v } // Usage: v1 = updateVertex(v1) - With a pointer, you can modify the original struct's fields directly through the pointer—no need for copies or return values. Like:
func updateVertexPtr(v *Vertex) { v.X = 10 } // Usage: updateVertexPtr(p) // modifies the original Vertex p points to
- To modify a plain struct's fields, you either modify the instance directly, or if it's passed to a function, you have to return the modified struct and reassign it (since the function gets a copy). For example:
Zero Value Behavior
- The zero value of a plain
VertexisVertex{0, 0}—all fields are set to their respective zero values (0 forinthere). - The zero value of
*Vertexisnil—it doesn't point to any valid struct instance. Trying to access fields on anilpointer (likenil.X) will cause a runtime panic.
- The zero value of a plain
Why Use a Pointer Instead of a Plain Struct?
Performance for Large Structs
If your struct has many fields or large data (like astructwith a big slice or string), copying the entire struct every time you pass it around is inefficient. Pointers let you pass just a small address instead, saving memory and CPU cycles.Share & Maintain a Single State
When multiple parts of your code need to work with the same struct instance (like a configuration object or a shared data structure), pointers ensure all changes apply to the same underlying data. No more dealing with out-of-sync copies.Interface Compliance
Some interfaces require methods with pointer receivers. For example, if you have an interface:type Movable interface { Move(dx, dy int) }And you define
Moveas a pointer receiver:func (v *Vertex) Move(dx, dy int) { v.X += dx v.Y += dy }Only
*Vertextypes will satisfy theMovableinterface—plainVertexinstances won't, because Go doesn't automatically convert value types to pointers for interface implementation.Avoid Accidental Copying
Sometimes you don't want to create copies by mistake. Using a pointer makes it explicit that you're working with the original instance, which helps prevent bugs where you modify a copy and wonder why the original didn't change.
In your example, p = &Vertex{1, 2} creates a new Vertex instance and immediately takes its address, giving you a pointer to that instance. This is a concise way to create a struct and get a pointer to it in one line.
内容的提问来源于stack exchange,提问作者Tomy

