How to Initializing embedded struct field using a struct literal?

34,743 views
Skip to first unread message

Ray Hollett

unread,
Mar 14, 2010, 3:19:41 PM3/14/10
to golang-nuts
I cannot seem to find a way of initializing an embedded struct field
using a struct literal. For instance if I have a struct Person
containing a string field name and embed this in a struct Employee. If
I use -
me := Employee{name:"Me"}
then I get an "unknown Employee field 'name' in struct literal " error
message from the 8g compiler.

I notice that the embedded example in Effective Go uses a function for
initializing an embedded field, so is not much help as I want to use a
struct literal.

Ostsol

unread,
Mar 14, 2010, 3:35:48 PM3/14/10
to golang-nuts
You initialize an embedded struct as if it were any other field. For
example:

type Person struct {
name string
}

type Employee struct {
Person
}

func main() {
dude := Employee{Person{"Me"}}
// or dude:= Employee{Person:Person{"Me"}}
}

-Daniel

Ray Hollett

unread,
Mar 14, 2010, 4:04:33 PM3/14/10
to golang-nuts
Thanks Ostsol your second line is what I needed -
dude:=Employee{Person:Person{"Me"}}

This is as I also have a field "number" in Employee that I also want
to initialize. But with your first line changed to
dude:=Employee{Person{"Me"}, number:1}
I get the error message - "mixture of field:value and value
initializers".
However, I really don't understand the logic behind your second line,
and would like to know how you came up with it from the Go docs.

Peter Bourgon

unread,
Mar 14, 2010, 4:18:36 PM3/14/10
to golang-nuts
On Sun, Mar 14, 2010 at 10:04 PM, Ray Hollett <holl...@googlemail.com> wrote:
> Thanks Ostsol your second line is what I needed -
> dude:=Employee{Person:Person{"Me"}}
>
> This is as I also have a field "number" in Employee that I also want
> to initialize. But with your first line changed to
> dude:=Employee{Person{"Me"}, number:1}
> I get the error message - "mixture of field:value and value
> initializers".
> However, I really don't understand the logic behind your second line,
> and would like to know how you came up with it from the Go docs.

I'm assuming your Employee struct is now of the form

type Employee struct {
Person
number int
}

If so, as described in Effective Go, "Constructors and composite
literals", you can construct structs using { } syntax in two ways:

1. Providing the values for each (and every) field in order, eg.

dude := Employee{ Person{"Me"}, 1 }

2. Or, by using field:value initializers for any number of fields in
any order, eg.

dude := Employee{ Person:Person{"Me"}, number:1 } or
dude := Employee{ number:1, Person:Person{"Me"} } or
dude := Employee{ Person:Person{"Me"} } (number gets default value of 0)

But, you can't mix and match those styles, as you've attempted to do.

Steven

unread,
Mar 14, 2010, 4:23:47 PM3/14/10
to peter....@gmail.com, golang-nuts
On Sun, Mar 14, 2010 at 4:18 PM, Peter Bourgon <peterb...@gmail.com> wrote:

     dude := Employee{ Person:Person{"Me"} }  (number gets default value of 0)
 
In a language that has done a lot to reduce stuttering, I've found this case an uncommon eyesore.

Peter Bourgon

unread,
Mar 14, 2010, 4:35:48 PM3/14/10
to golang-nuts

Well, it's not required syntax, but I'm with you in spirit. On the
same point: as currently implemented, being able to directly reference
embedded fields' members feels more like syntactic sugar than a
first-class-feature. If I have

type Foo struct {
Alpha string
}

type Bar struct {
Beta int
}

type Foobar struct {
Foo
Bar
Delta string
}

it's a real shame I can't create a Foobar via

fb := Foobar{"abc", 64, "xyz"} // or
fb := Foobar{Alpha:"abc", Beta:64, Delta:"xyz"}

or do a json.Unmarshal on `{ "Alpha": "abc", "Beta": 64, "Delta":
"xyz" }`, given that (once created) the following is totally valid:

fmt.Printf("%s %d %d\n", fb.Alpha, fb.Beta, fb.Delta)

If this worked, it would really help cut down on the amount of
copy/paste and code duplication I'm currently having to do. I wonder
if there's a technical reason this isn't possible?

Peter Bourgon

unread,
Mar 14, 2010, 4:37:13 PM3/14/10
to golang-nuts
>  fmt.Printf("%s %d %d\n", fb.Alpha, fb.Beta, fb.Delta)

fmt.Printf("%s %d %s\n", fb.Alpha, fb.Beta, fb.Delta), of course :|

Steven

unread,
Mar 14, 2010, 4:43:39 PM3/14/10
to Peter Bourgon, golang-nuts
http://groups.google.com/group/golang-nuts/browse_thread/thread/ad301a5c969f1bac/086f77b237b929da?lnk=gst&q=struct+literal#086f77b237b929da
I brought this up a while ago. The response was that, while it makes sense for embedded values, what do you do about embedded pointers?

Ray Hollett

unread,
Mar 14, 2010, 4:56:19 PM3/14/10
to golang-nuts
I can understand the logic of not mixing field:value and value
initializers, but
not the logic of "Person:Person{}" syntax. I have revisited the Go
docs and
cannot see anything that would lead me to the "Person:Person{}"
syntax.

On Mar 14, 8:18 pm, Peter Bourgon <peterbour...@gmail.com> wrote:

Peter Bourgon

unread,
Mar 14, 2010, 4:59:54 PM3/14/10
to golang-nuts
Since the Person field is unnamed in the Employee struct, you can
(must) refer to it directly by way of its type name. So in
"Person:Person{}", the first Person refers to the field in the
Employee struct, and the second Person is a Person constructor, same
as if you did:

p := Person{...}

Ray Hollett

unread,
Mar 15, 2010, 7:44:51 AM3/15/10
to golang-nuts
Thanks Steven for the reference to the previous thread. I am now
understanding more of the context of struct embedding and Russ Cox's
summary of the compiler difficulties is enlightening.

For my use, struct Embedding is excellent at run time in that the
methods and fields of the embedded structs appear at run time as top
level methods and fields, giving simple composition. Unfortunately
this is not reflected in initialization with struct literals and I end
up with initializing as in:
dude := Employee{Person:Person{firstName:"John", secondName:"Doe"},
number:1}
when what I would like to be able to use is:
dude := Employee{firstName:"John", secondName:"Doe", number:1}

Perhaps the problem is that what I want is a simple macro like include
facility to provide a union of the structs, not the complex tree
structured embedding type facility. I realize that this would not
allow for multiple fields with the same name, but I am not sure that
is a problem in real programs. This macro approach may also remove the
complex compiler writing issues.

On Mar 14, 8:43 pm, Steven <steven...@gmail.com> wrote:
> On Sun, Mar 14, 2010 at 4:35 PM, Peter Bourgon <pe...@bourgon.org> wrote:

> > On Sun, Mar 14, 2010 at 10:23 PM, Steven <steven...@gmail.com> wrote:
> > > On Sun, Mar 14, 2010 at 4:18 PM, Peter Bourgon <peterbour...@gmail.com>

> http://groups.google.com/group/golang-nuts/browse_thread/thread/ad301...

mattn

unread,
Feb 18, 2011, 12:36:48 AM2/18/11
to golan...@googlegroups.com
If there is only one about the embed struct, it can become syntax sugar in future. but...
For implementing polymorphism, we may use interface.  And we have to assign the instance to each interfaces(pleonasm?).
Of course, go's behavior is good for that we can set another instances for thems.
---------------------------
package main

type Animal interface {
Name() string
Sing()
}
type Worker interface {
DoWork()
}


type Monkey struct {
name string
Animal
}
func (m Monkey) DoWork() { println("No! I don't!") }
func (m Monkey) Sing() { println("Screech!") }
func (m Monkey) Name() string { return m.name }


type Person struct {
name string
Animal
}
func (p Person) DoWork() { println("Yes, Sir!") }
func (p Person) Sing() { println("LaLaLa!") }
func (p Person) Name() string { return p.name }

type Employee struct {
Animal
Worker
}

func main() {
//e := Employee{Person{name:"mattn"}}
p := Person{name:"mattn"}
e := Employee{Animal:p, Worker:p}
print("I am ", e.Name(), ": ")
e.DoWork()
e.Sing()

m := Monkey{name:"george"}
e = Employee{Animal:m, Worker:m}
print("I am ", e.Name(), ": ")
e.DoWork()
e.Sing()
}
---------------------------
I'm interesting in this issue.

Reply all
Reply to author
Forward
0 new messages