30

I have these types:

type Value interface{}

type NamedValue struct {
    Name  string
    Value Value
}

type ErrorValue struct {
    NamedValue
    Error error
}

I can use v := NamedValue{Name: "fine", Value: 33}, but I am not able to use e := ErrorValue{Name: "alpha", Value: 123, Error: err}

Seems that embedding syntax was ok, but using it doesn't work?

Mistu4u
  • 5,132
  • 15
  • 53
  • 91
Ayman
  • 11,265
  • 16
  • 66
  • 92

3 Answers3

46

Embedded types are (unnamed) fields, referred to by the unqualified type name.

Spec: Struct types:

A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct. An embedded type must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.

So try:

e := ErrorValue{NamedValue: NamedValue{Name: "fine", Value: 33}, Error: err}

Also works if you omit the field names in the composite literal:

e := ErrorValue{NamedValue{"fine", 33}, err}

Try the examples on the Go Playground.

icza
  • 389,944
  • 63
  • 907
  • 827
  • Omitting the field names does work as mentioned, however if your struct has many fields then unfortunately you'll also be required to pass them. For example for a struct with four properties, if your embedded struct is one of the first fields then you'll need to initialize it like `ErrorValue{nil, NamedValue{"fine", 33}, nil, nil}` which doesn't look as clean as passing the unqualified type name of the embedded struct in. The first method as mentioned is a bit better but I can't help but feeling it's a bit unnecessarily complicated and unwieldy (compared to a language like Python at least) – rv.kvetch Mar 27 '21 at 02:43
6

For deeply nested structs, the accepted answer's syntax is a little verbose. For example, this :

package main

import (
    "fmt"
)

type Alternative struct {
    Question
    AlternativeName string
}

type Question struct {
    Questionnaire
    QuestionName  string
}

type Questionnaire struct {
    QuestionnaireName string
}

func main() {
    a := Alternative{
        Question: Question{
            Questionnaire: Questionnaire{
                QuestionnaireName: "q",
            },
        },
    }
    fmt.Printf("%v", a)
}

(Go playground)

Could be rewritten like this:

a := Alternative{}
a.QuestionnaireName = "q"
Federico
  • 3,650
  • 4
  • 32
  • 45
4

In addition to the wonderful answer by icza.

you can simply do this:

v := NamedValue{Name: "fine", Value: 33}
e := ErrorValue{NamedValue:v, Error: err}

and it works just fine. checkout the example Here