19

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.

1
  • 2
    Don't think so. This question specifically asks about the result of &Variable vs new(Type) when passed to a pointer type taking function. 10990174 doesn't ask nor answer that. Commented Sep 9, 2012 at 8:11

4 Answers 4

17

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

Sign up to request clarification or add additional context in comments.

Comments

6

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}

Comments

1

One assigns a nil pointer, the other assigns a pointer to a zero initialized struct. In a linked list style example:

type Node struct { 
  Data int
  Next *Node
}

Create a node in each of the mentioned ways

var node1 = new(Node)
var node2 *Node

Printing the variables gives

&{0 <nil>}
<nil>

This means that if you were to try to do this

fmt.Println(node1.Data)
fmt.Println(node2.Data)

The first will print out 0, the second will throw a nil pointer dereference exception and panic.

Comments

-4

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.

18 Comments

The only difference is that new() returns a pointer to a variable while var allows you to declare a variable. This answer would make sense if Go recognized the difference between stack and heap in the language. See dystroy's answer below and my own answer to another question stackoverflow.com/a/10990287/727643
@StephenWeinberg: I stand by my answer. (Of course after I now double checked it). Please specify the perceived faults wrt the specs. Also, please tell me what (reasonable) alternative to memory allocation is for implementing new. Also, please let me know which existing Go compiler(s) use that alternative. Thanks in advance. I realize the specs don't talk about stack or heap. That doesn't rule out talking about how the implementation works, especially if it aids to understanding. See also: research.swtch.com/godata
@jnml: another way to implement new anywhere is the same thing the OP did. var b bar; ptrb := &b. The two ways he listed are identical according to the spec. You are allowed to talk about the implementation if you mention it is implementation dependent. However, you are wrong about the implementation. Both gc and gccgo will allocate them to the heap in both cases. In both cases the escape analysis forces them to put the variable on the heap.
While you were right about the difference between your two looping examples, they missed the point of the question. If you put the var b bar inside the loop in the first example, it would do the exact same thing as the second example. This is what the OP asked in the first place.
You are confused. new(T) and &T{} are the same thing. The only reason new(T) exists is because the latter form cannot be used with primitive types (e.g. int). The two code snippets are different, but that's because in the first you allocate outside the loop and in second you allocate inside the loop. It's different code, you have not answered what the OP asked, instead you have posted a misinformed and confusing answer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.