Difference between new() and create a struct returning an address

type Person struct {
Id int
First_Name string
Last_Name string
}

func person_new() *Person{
var b *Person = new(Person)
b.Id=1
b.First_Name="John"
b.Last_Name = "Hernandez"
return b;
}

func person_new2() *Person{
var b Person;
b.Id=1
b.First_Name="John"
b.Last_Name = "Hernandez"
return &b;
}

These two functions do exactly the same thing but my question is the first one is more inefficient right? In the first function, I will reserve more memory because I have to reserve space to my struct Person and to my pointer and in the second one only I will reserve space to my struct, right? And because I create a pointer to my struct (Person), the access to my attributes (Id, First_name, Last_name) will be slower than function 2 (I have to access to my pointer=&Person (put it in a register) and only then I will be able to access to my attributes)?

There is no difference between the two

With a slight modification of the second variant, you can create and initialize a Person in a single step:

    func NewPerson() *Person {
	return &Person{
		Id:        1,
		FirstName: "John",
		LastName:  "Hernandez",
	}
}

(Side note - In Go, CamelCase is preferred over snake_case)

But why there is no difference between the two? in first one i create a pointer to a struct and in second one I only create a struct.

Because in both cases you return the address of the newly constructed structure. From the point of view of the caller of this code there is no difference.

Yes you are right i said that, in my post (“These two functions do exactly the same”) but my question is about efficiency. In first one i reserve space to a struct and to a pointer that point to the space that i created. But in second one i only have a struct not a pointer, so i will use less memory in function two, right?

You are returning a pointer, so certainly there exists a pointer. But you can discover the difference for yourself; put the above in a file with a package declaration, go build -gcflags -S thefile.go to get the assembly output. Diff the two functions. After removing the line numbers, the following differences remain for me:

jb@unu:~/tmp $ diff -u asm asm2
--- asm	2017-02-13 14:16:22.000000000 +0100
+++ asm2	2017-02-13 14:16:15.000000000 +0100
@@ -1,5 +1,5 @@
-"".person_new t=1 size=213 args=0x8 locals=0x20
-	0x0000 00000 (/Users/jb/tmp/test.go)	TEXT	"".person_new(SB), $32-8
+"".person_new2 t=1 size=213 args=0x8 locals=0x20
+	0x0000 00000 (/Users/jb/tmp/test.go)	TEXT	"".person_new2(SB), $32-8
 	0x0000 00000 (/Users/jb/tmp/test.go)	MOVQ	(TLS), CX
 	0x0009 00009 (/Users/jb/tmp/test.go)	CMPQ	SP, 16(CX)
 	0x000d 00013 (/Users/jb/tmp/test.go)	JLS	203
@@ -13,7 +13,7 @@
 	0x002c 00044 (/Users/jb/tmp/test.go)	PCDATA	$0, $0
 	0x002c 00044 (/Users/jb/tmp/test.go)	CALL	runtime.newobject(SB)
 	0x0031 00049 (/Users/jb/tmp/test.go)	MOVQ	8(SP), AX
-	0x0036 00054 (/Users/jb/tmp/test.go)	MOVQ	AX, "".b+16(SP)
+	0x0036 00054 (/Users/jb/tmp/test.go)	MOVQ	AX, "".&b+16(SP)
 	0x003b 00059 (/Users/jb/tmp/test.go)	MOVQ	$1, (AX)
 	0x0042 00066 (/Users/jb/tmp/test.go)	MOVQ	$4, 16(AX)
 	0x004a 00074 (/Users/jb/tmp/test.go)	MOVL	runtime.writeBarrier(SB), CX
@@ -38,14 +38,14 @@
 	0x009e 00158 (/Users/jb/tmp/test.go)	MOVQ	CX, 8(SP)
 	0x00a3 00163 (/Users/jb/tmp/test.go)	PCDATA	$0, $1
 	0x00a3 00163 (/Users/jb/tmp/test.go)	CALL	runtime.writebarrierptr(SB)
-	0x00a8 00168 (/Users/jb/tmp/test.go)	MOVQ	"".b+16(SP), AX
+	0x00a8 00168 (/Users/jb/tmp/test.go)	MOVQ	"".&b+16(SP), AX
 	0x00ad 00173 (/Users/jb/tmp/test.go)	JMP	132
 	0x00af 00175 (/Users/jb/tmp/test.go)	MOVQ	DX, (SP)
 	0x00b3 00179 (/Users/jb/tmp/test.go)	LEAQ	go.string."John"(SB), CX
 	0x00ba 00186 (/Users/jb/tmp/test.go)	MOVQ	CX, 8(SP)
 	0x00bf 00191 (/Users/jb/tmp/test.go)	PCDATA	$0, $1
 	0x00bf 00191 (/Users/jb/tmp/test.go)	CALL	runtime.writebarrierptr(SB)
-	0x00c4 00196 (/Users/jb/tmp/test.go)	MOVQ	"".b+16(SP), AX
+	0x00c4 00196 (/Users/jb/tmp/test.go)	MOVQ	"".&b+16(SP), AX
 	0x00c9 00201 (/Users/jb/tmp/test.go)	JMP	99
 	0x00cb 00203 (/Users/jb/tmp/test.go)	NOP
 	0x00cb 00203 (/Users/jb/tmp/test.go)	PCDATA	$0, $-1

The only difference is that in one case it needs the address of the symbol b (when it is not a pointer by itself), in the other it is already a pointer. I suspect that in the end these are the same instructions anyway. There is no other difference in the generated code. Specifically, the number of allocations is identical.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.