Why should I use the & sign on structs?
The comments pretty much spell it out:
v1 = Vertex{1, 2} // has type Vertex
p = &Vertex{1, 2} // has type *Vertex
As in many other languages, &
takes the address of the identifier following it. This is useful when you want a pointer rather than a value.
If you need to understand more about pointers in programming, you could start with this for go, or even the wikipedia page.
It's true that p
(&Vertex{}
) has type *Vertex
and that c
(Vertex{}
) has type Vertex
.
However, I don't believe that statement really answers the question of why one would choose one over the other. It'd be kind of like answering the question "why use planes over cars" with something like "planes are winged, cars aren't." (Obviously we all know what wings are, but you get the point).
But it also wouldn't be very helpful to simply say "go learn about pointers" (though I think it is a really good idea to so nonetheless).
How you choose basically boils down to the following.
Realize that
&Vertex{}
andVertex{}
are fundamentally initialized in the same way.- There might be some low-level memory allocation differences (i.e. stack vs heap), but you really should just let the compiler worry about these details
What makes one more useful and performant than the other is determined by how they are used in the program.
"Do I want a pointer to the struct (
p
), or just the struct (c
)?"- Note that you can get a pointer using the
&
operator (e.g.&c
); you can dereference a pointer to get the value using*
(e.g.*p
)- So depending on what you choose, you may end up doing a lot of
*p
or&c
- Bottom-line: create what you will use; if you don't need a pointer, don't make one (this will help more with "optimizations" in the long run).
- So depending on what you choose, you may end up doing a lot of
- Note that you can get a pointer using the
- Should I use
Vertex{}
or&Vertex{}
?- For the
Vertex
given in your example, I'd chooseVertex{}
to a get a simple value object. - Some reasons:
Vertex
in the example is pretty small in terms of size. Copying is cheap.- Garbage collection is simplified, garbage creation may be mitigated by the compiler
- Pointers can get tricky and add unnecessary cognitive load to the programmer (i.e. gets harder to maintain)
- Pointers aren't something you want if you ever get into concurrency (i.e. it's unsafe)
Vertex
doesn't really contain anything worth mutating (just return/create a newVertex
when needed).
- Some reasons why you'd want
&Struct{}
- If
Struct
has a member caching some state that needs to be changed inside the original object itself. Struct
is huge, and you've done enough profiling to determine that the cost of copying is significant.- As an aside: you should try to keep your
struct
s small, it's just good practice.
- As an aside: you should try to keep your
- You find yourself making copies by accident (this is a bit of a stretch):
v := Struct{} v2 := v // Copy happens
v := &Struct{} v2 := v // Only a pointer is copied
- If
- For the