声明struct VS的变量之间有什么区别

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?

Declaring a variable vs initializing it with zero value

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.

Memory allocation by declaring a variable

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 type T 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.