type person struct {
age int
gender string
}
(1)var tom person
(2)var jim person = person{}
In line one,tom is declared as person,line 2,jim is declared as person and assigned an empty person to it,what is the difference between these two?The default value are the same in both ways.Will line 1 allocate memory storage once it is declared without assigning anything to it?
Same thing as
var i int
Does the code above allocate memory or just denote an address as doing this
var i *int = new(int)
I know the i variable has different meanings in these two code,the first is a variable of type int and the second is a pointer,but the first i should also represent some address in the memory which means it allocate a certain address to i and defaults "i" to 0?
In Go, all variables declared without initializers are initialized to the so-called zero values appropriate for their types. Since for a struct person
its zero value is the expression person{}
both cases, (1) and (2) do the same thing. I reckon the compiler will generate the same code for them.
To cite the spec:
A variable declaration creates a variable, binds an identifier to it and gives it a type and optionally an initial value.
…
If a list of expressions is given, the variables are initialized by assigning the expressions to the variables in order; all expressions must be consumed and all variables initialized from them. Otherwise, each variable is initialized to its zero value.
The declaration var i int
declares a variable and initializes it. In some sense, this does mean allocating memory (and initializing it) but I'd not dig that deep: you should be fine with the fact the compiler will arrange for the variable to exist.
As to whether that "denotes an address" or not depends on how you look at this: it's not the programmer's business to think about how the variable is laid out in memory—the name of the variable is a handle on its value, and the compiler is free to provide such access however it pleases. I mean, the compiler may internally store the address of this variable somewhere and use it but you should not be concerned with it.
The var i *int = new(int)
declaration declares a pointer to an anonymous variable (a memory block which has the semantics of a certain type "attached" to it), initializes the memory of that variable with the zero value appropriate for its type and then assigns the address of that memory block to the variable you're declaring.
To cite the spec:
The built-in function
new
takes a typeT
and returns a value of type*T
. The memory is initialized as described in the section on initial values.
In this case, you operate on a pointer, not on a variable itself. So these two declarations do quite different things as they declare different types of variables, and the resulting variables have different semantics.
Possibly the chief difference between var i int
and var p *int = new(int)
lies in that in the former case the variable is created "right away" (statically) while in the latter case the memory for the anonymous variable is initialized dynamically. But again do not be too attached to this: when the execution hits the var i int
declaration, you cannot know for sure what exactly happens in the program other than the variable named i
of type int
becomes available. For instance, the compiler is free to use "the heap" to allocate it, not "the stack" (assuming a typical H/W architecture).
While the definitions of tom
and jim
have the same effect, they produce different machine code. I put the two declarations into a simple function, compiled it with go tool 6g -S foo.go
, and got this assembly for the output for the two declarations:
0004 (foo.go:8) TYPE tom+-48(SP){"".person},$24
0005 (foo.go:8) TYPE jim+-24(SP){"".person},$24
0006 (foo.go:9) LEAQ tom+-48(SP),DI
0007 (foo.go:9) MOVQ $0,AX
0008 (foo.go:9) STOSQ ,
0009 (foo.go:9) STOSQ ,
0010 (foo.go:9) STOSQ ,
0011 (foo.go:10) LEAQ statictmp_0000+0(SB),BX
0012 (foo.go:10) LEAQ jim+-24(SP),BP
0013 (foo.go:10) MOVQ BP,DI
0014 (foo.go:10) MOVQ BX,SI
0015 (foo.go:10) MOVSQ ,
0016 (foo.go:10) MOVSQ ,
0017 (foo.go:10) MOVSQ ,
So space on the stack has been allocated on the stack for each variable, but tom
is initialised by storing zeroes to its memory while jim
is initialised by copying from some other memory (probably something in the read only data segment of the program). For most cases, this is probably not going to matter: if variable initialisation is a large part of your program runtime then you probably aren't doing much.
But if you have a particularly large variable (e.g. a large array) and want it initialised to its zero value, you might start to see a difference.