views:

106

answers:

2

What difference there is when you access to another struct by value or by a pointer?
When should be used each one of them?

type foo_ struct {
    st uint8
    nd uint8
}

type bar struct {
    rd  uint8
    foo foo_
}

type barP struct {
    rd  uint8
    foo *foo_
}
+1  A: 

The answer is largely independent of language - the equivalent in C has the same issues.

When you have an embedded value (as in bar), then your structure is big enough to hold the complete sub-structure and the other part.

When you have a pointer to a value (as in barP), then a number of structures of type barP may share the same foo. When any of the barP modifies a part of the foo it points to, it affects all the other barP structures that point to the same place. Also, as the commentary suggests, you have to manage two separate objects - the barP and the foo as against one with the plain bar type.

In some languages, you would have to worry about dangling pointers and uninitialized values etc; Go is garbage collected and generally more type-safe than other languages.

So, use a pointer when you want multiple barP objects to share the same foo object; otherwise, use an explicit member object, rather than a pointer to an object.

Jonathan Leffler
When a variable of `type barP` is declared or allocated, the initial value of foo will be a `nil` pointer.
peterSO
+2  A: 

If you declare or allocate a variable of type bar, you reserve and initialize to zero memory for both rd uint8 and foo foo_. There is always one variable of type foo_ embedded in a variable of type bar.

var b bar  // declare b

If you declare or allocate a variable of type barP, you reserve and initialize to zero memory for both rd uint8 and foo *foo_. A zero value pointer is a nil pointer. No variable of type foo_ is allocated; you must do that separately. There is either zero (foo == nil) or one variable of type foo_ pointed to by a variable of type barP. A variable of type barP may point to the same variable of type foo_ as other variables of type barP, sharing the same copy of the variable of type foo_. A change to a shared copy is seen by all variables that point to it.

var bp barP         // declare bp
bp.foo = new(foo_)  // allocate bp.foo

Which one to use depends on the properties of type bar versus type barP. Which type more closely reflects the problem that you are trying to solve?

For example, consider this invoice problem. We always have a billing address; we are always going to ask for our money. However, we often ship to the billing address, but not always. If the shipping address is nil, use the billing address. Otherwise, use a separate shipping address. We have two warehouses, and we always ship from one or the other. We can share the two warehouse locations. Since we don't send an invoice until the order is shipped from the warehouse, the warehouse location will never be nil.

type address struct {
    street string
    city   string
}

type warehouse struct {
    address string
}

type invoice struct {
    name      string
    billing   address
    shipping  *address
    warehouse *warehouse
}
peterSO