They only differ in what the type of the local variable is. Whether to prefer one over the other depends entirely on how you would use that variable in the remainder of the function's body. If you are always passing it around (meaning use it on the right-hand side of an assignment, as an argument to a function call, or returning it) as a pointer, use the pb := &Student{...}
form. If you intend to create (shallow) copies of it, the b := Student{...}
form might be more convenient. This is however purely based on the fact that typing pb
is easier than &b
, and that typing b
is easier than *pb
. If you apply these substitutions everywhere (except for in the context of field accesses, where it is allowed but not mandatory, see below), they are completely interchangeable.
If you want to be able to set the variable holding the struct (pointer) to nil
, use a pointer, obviously. But this can also be solved by introducing a new, pointer-typed variable and setting that to either nil
or &b
.
Some types in Go cannot be copied (this is typically accomplished by embedding a [0]sync.Mutex
field in the struct, which takes up no space but triggers the "mutex copy" error of the compiler). An example would be protobuf structs. For these, it is almost always preferable to use the pointer form; however, this is not required, as the initialization via b := Student{...}
is not a copy.
Go allows transparently dereferencing when accessing struct fields. b.Name
, (&b).Name
, pb.Name
, (*pb).Name
all work and are equivalent. Note however that transparent dereferencing only works over one level, (&pb).Name
will result in a compiler error.