Home > database >  Golang: The differences between these two ways of initializing struct
Golang: The differences between these two ways of initializing struct

Time:02-06

I am wondering what the differences are between those two ways of initializing a struct in Go. Does the second one give you a pointer storing the address of the struct? But they have the same syntax if we want to change the field variables, so how are they different?

I can de-reference the pointer, apparently. But do they have different functionalities? In what scenario would I prefer one over the other?

b := Student{Name:"Bob"}
pb := &Student{Name:"Bob", Age:8,}

CodePudding user response:

They only differ in what the type of the local variable is. Whether to prefer one over the other depends entirely on how you would use that variable in the remainder of the function's body. If you are always passing it around (meaning use it on the right-hand side of an assignment, as an argument to a function call, or returning it) as a pointer, use the pb := &Student{...} form. If you intend to create (shallow) copies of it, the b := Student{...} form might be more convenient. This is however purely based on the fact that typing pb is easier than &b, and that typing b is easier than *pb. If you apply these substitutions everywhere (except for in the context of field accesses, where it is allowed but not mandatory, see below), they are completely interchangeable.

If you want to be able to set the variable holding the struct (pointer) to nil, use a pointer, obviously. But this can also be solved by introducing a new, pointer-typed variable and setting that to either nil or &b.

Some types in Go cannot be copied (this is typically accomplished by embedding a [0]sync.Mutex field in the struct, which takes up no space but triggers the "mutex copy" error of the compiler). An example would be protobuf structs. For these, it is almost always preferable to use the pointer form; however, this is not required, as the initialization via b := Student{...} is not a copy.

Go allows transparently dereferencing when accessing struct fields. b.Name, (&b).Name, pb.Name, (*pb).Name all work and are equivalent. Note however that transparent dereferencing only works over one level, (&pb).Name will result in a compiler error.

CodePudding user response:

The composite literals differ in the initialization of the Age field. The first sets the field to the zero value. The second sets the field to the number 8. Otherwise, the initialization of the struct values is identical.

What happens next is where the key difference lies. The first example assigns the value to a variable named b. The second example takes assigns the value to an anonymous variable; takes the address of the variable; and assigns the result to a variable named pb.

The type of b is the struct type and the type of pb is a pointer to the struct type.

See I don't understand when to use pointers on go to see a discussion on why one might want to use a pointer.

  • Related