Problem: You want to create an instance of a struct.
Solution: Create a struct instance directly using the name of the struct, or a pointer to a struct instance using the new keyword.
There are two ways to create an instance of a struct. The first is to directly use the name of the struct:
type Person struct { Id int Name string Email string } person := Person{}
This creates an empty struct instance, which you can populate subsequently by accessing the struct fields:
person.Id = 1 person.Name = "Chang Sau Sheong" person.Email = "sausheong@email.com"
A quicker way is to create and initialize the struct instance at the same time:
person := Person{1, "Chang Sau Sheong", "sausheong@email.com"}
This is pretty straightforward. However, you need to specify all field values.
You can also make the code clearer by indicating the name of the data field during initialization. When you do this, you can leave out field values:
person := Person{ Id: 1, Email: "sausheong@email.com", }
To create a reference to a struct instance you can use the address operator ( & ):
person := &Person{ Id: 1, Name: "Chang Sau Sheong", Email: "sausheong@email.com", }
This brings us to the second way of creating struct instances, which is to use the new built-in function. The new function is used for more than creating struct instances though; it can be used to create references to a specified type. In this case, you’re using it to create a reference to a struct instance:
person := new(Person)
When creating a struct instance this way, new returns a reference to the struct instance and not the actual instance itself. In other words, this is equivalent to the following code:
person := &Person{}
Should you pass a struct instance by copy or by reference? The usage is quite clear; you would want to pass by reference if you want the function to modify the struct instance in some way. If not, both ways work. In this case, wouldn’t it be better to always pass by reference so you don’t need to think too much about it? Not really, because there is a difference in performance. There are two ways we normally pass struct instances around.
The first is passing a struct instance down to a function either by copy or by reference.
func byCopyDown(p Person) { _ = fmt.Sprintf("%v", p) } func byReferenceDown(p *Person) { _ = fmt.Sprintf("%v", p) }
Passing down by copy is faster than passing down by reference.
Now let’s look at the second direction, which is passing the struct instance by copy or by reference back from the function to the caller.
func byCopyUp() Person { return Person{ Id: 1, GivenName: "Sau Sheong", FamilyName: "Chang", Email: "sausheong@email.com", } } func byReferenceUp() *Person { return &Person{ Id: 1, GivenName: "Sau Sheong", FamilyName: "Chang", Email: "sausheong@email.com", } }
Passing up by copy is much faster than passing up by reference.
In general, if you don’t need to pass structs around by reference, you should stick with passing by copy.