Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang struct initialization

Tags:

go

There is a simple struct like this:

type Event struct {     Id         int     Name       string } 

What is the difference between these two initialization methods?

e1 := Event{Id: 1, Name: "event 1"} e2 := &Event{Id: 2, Name: "event 2"} 

Any why would I use either of these initialization methods?

like image 522
kind_robot Avatar asked Sep 28 '16 21:09

kind_robot


People also ask

How do you initialize a struct in Go?

2 ways to create and initialize a new structThe new keyword can be used to create a new struct. It returns a pointer to the newly created struct. You can also create and initialize a struct with a struct literal. An element list that contains keys does not need to have an element for each struct field.

How do you initialize a struct value?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).

How do I create a struct inside a struct in Golang?

A structure or struct in Golang is a user-defined type, which allows us to create a group of elements of different types into a single unit. Any real-world entity which has some set of properties or fields can be represented as a struct. Go language allows nested structure.

How do you use structs in Golang?

A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct. This concept is generally compared with the classes in object-oriented programming.


2 Answers

The first method

e1 := Event{Id: 1, Name: "event 1"} 

is initializing the variable e1 as a value with type Event.

The second

e2 := &Event{Id: 1, Name: "event1"} 

is initializing e2 as a pointer to a value of type Event As you stated in the comments, the set of methods defined on a value of a given type are a subset of the set of methods defined on a pointer to a value of that type. This means that if you have a method

func (e Event) GetName() string {     return e.Name } 

then both e1 and e2 can call this method, but if you had another method, say:

func (e *Event) ChangeName(s string) {     e.Name = s } 

Then e1 is not able to use the ChangeName method, while e2 is.

This (e1 is not able to use the ChangeName method, while e2 is) is not the case (although it may have been at the time of writing for this help), thanks to @DannyChen for bringing this up and @GilbertNwaiwu for testing and posting in the comments below.

(To address the striked out section above: The set of methods defined on a struct type consist of the methods defined for the type and pointers to the type.

Instead, Go now automatically dereferences the argument to a method, so that if a method receives a pointer, Go calls the method on a pointer to that struct, and if the method receives a value, Go calls the method on the value pointed to by that struct. At this point my attempt to update this answer may be missing something important in semantics so if someone would like to correct this or clarify feel free to add a comment pointing to a more comprehensive answer. Here is a bit from the go playground illustrating this issue: https://play.golang.org/p/JcD0izXZGz.

To some extent, this change in how pointers and values work as arguments to methods defined on function affects some areas of the discourse below but I will leave the rest unedited unless someone encourages me to update it as it seems to be more or less correct within the context of general semantics of languages that pass by value vs. pointer.)

As to the difference between pointers and values, this example is illustrative, as pointers are ordinarily used in Go to allow you to mutate the values a variable is pointing to (but there are many more reasons one might use pointers as well! Although for typical use, this is normally a solid assumption). Thus, if you defined ChangeName instead as:

func (e Event) ChangeName(s string) {     e.Name = s } 

This function would not be very useful if called on the value receiver, as values (not pointers) won't keep changes that are made to them if they're passed into a function. This has to do with an area of language design around how variables are assigned and passed: What's the difference between passing by reference vs. passing by value?

You can see this on this example in the Go Playground: https://play.golang.org/p/j7yxvu3Fe6

like image 192
Clemente Cuevas Avatar answered Sep 30 '22 11:09

Clemente Cuevas


The type of e1 is Event the type of e2 is *Event. The initialization is actually the same (using composite literal syntax, also not sure if that jargon is Go or C# or both?) but with e2 you using the 'address of operator' & so it returns a pointer to that object rather than the instance itself.

like image 43
evanmcdonnal Avatar answered Sep 30 '22 10:09

evanmcdonnal