Schwern
Schwern

Reputation: 164629

How do I initialize a composed struct in Go?

Let's say I have a struct with another struct embedded in it.

type Base struct {
    ID string
}

type Child struct {
    Base
    a int
    b int
}

When I go to initialize Child, I can't initialize the ID field directly.

// unknown field 'ID' in struct literal of type Child
child := Child{ ID: id, a: a, b: b }

I instead have to initialize the ID field separately.

child := Child{ a: 23, b: 42 }
child.ID = "foo"

This would seem to violate encapsulation. The user of Child has to know there's something different about the ID field. If I later moved a public field into an embedded struct, that might break initialization.

I could write a NewFoo() method for every struct and hope everyone uses that, but is there a way to use the struct literal safely with embedded structs that doesn't reveal some of the fields are embedded? Or am I applying the wrong pattern here?

Upvotes: 36

Views: 16355

Answers (1)

Thundercat
Thundercat

Reputation: 120931

Use nested composite literals to initialize a value in a single expression:

child := Child{Base: Base{ID: id}, a: a, b: b}

Go issue 9859 proposes a change to make composite literals consistent with field access for embedded types. This change will allow the Child{ ID: id, a: a, b: b } expression from the question.

Embedded types do not provide encapsulation in the sense that the feature does not restrict direct access the embedded type. An application can directly access child.Base.ID in addition to using child.ID.

Upvotes: 54

Related Questions