You have a function with an argument, a pointer to a type.
type bar struct{...}
func foo(arg *bar)
Is there any difference between:
var b bar
foo(&b)
and
b := new(bar)
foo(b)
The use of new creates an allocation.
No, there is no difference, as, contrary to C, Go explicitly states that you can give a pointer to a locally created variable.
From the documentation :
Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns
Both should represent the same pointer to the same object initialized with the same default value.
The spec does mention:
After
type T struct { i int; f float64; next *T }
t := new(T)
the following holds:
t.i == 0
t.f == 0.0
t.next == nil
The same would also be true after
var t T
Also:
Taking the address of a composite literal (§Address operators) generates a pointer to a unique instance of the literal's value.
var pointer *Point3D = &Point3D{y: 1000}
There are a differences in certain situations. new(T)
, as the name implies, returns a, well, new instance of type T, while var b T
is a single instance, once and forever (err, actually until end of its lifetime == going out of scope, not reachable...).
Consider this loop
var b bar
for i := 0; i < 10; i++ {
foo(&b)
}
vs
var b *bar
for i := 0; i < 10; i++ {
b = new(b)
foo(b)
}
In the later case, if foo
for example stores its arg
in some container, results in 10 instances of bar
existing while the former case with only one - in variable b
.
Another difference is in the performance. The variable b
would be either a fully static global variable or will typically sit at a statically known offset in some function/method invocation record (a fancy name for usually a stack frame). new
OTOH, if not optimized out by the compiler, is a memory allocator call. Such call will cost some nonzero time. If made in a loop and not actually necessary, then it can make noticeable slowdown of some code path.