-1

I learnt that it is not allowed to embed slices or maps into Go structs. But I found two workarounds to this:

  1. Declare the slice or map outside the struct and embed it into the struct

    var mySlice []int
    
    type myStruct struct {
      mySlice
    }
    
  2. I don't really understand this second workaround, but I found it's called Composition and it's done by just omitting the var keyword when declaring the slice or map within the struct

    type myStruct struct {
      mySlice []int
    }
    

My first question is, can anyone explain why we can't directly embed slices and maps into a struct?

Second question: using the second workaround, is there any negative performance effect to that?

Third question: why do the first and second workaround work?

icza
  • 389,944
  • 63
  • 907
  • 827
Ercross
  • 519
  • 6
  • 17
  • 4
    Second is not a "workaround" - you just declared a field in the struct. https://tour.golang.org/moretypes/2 – zerkms Apr 08 '20 at 22:01
  • 2
    What you have in option 1 is definitely invalid. What you have in option 2 looks completely standard. What do you mean when you say "embed slices and maps into a struct"? Could you show an example of what you would call "embedding"? – Amit Kumar Gupta Apr 08 '20 at 22:02
  • @AmitKumarGupta they probably typoed `var` -> `type`. Then it works. – zerkms Apr 08 '20 at 22:03
  • @AmitKumarGupta, I don't understand what you mean by option 1 is invalid, but it works. What I mean by the phrase "embed slices and maps into a struct" is what I saw on this website: https://mariadesouza.com/2017/09/29/embedding-in-go/ – Ercross Apr 08 '20 at 22:12
  • 2
    Your first example is invalid, not because you cannot embed slices into structs, but because you cannot embed _variables_ into structs. `mySlice` is a named variable, not a type. If you change it to `type mySlice []int`, the rest of your coe works fine. – Jonathan Hall Apr 09 '20 at 09:40

1 Answers1

3

Spec: Struct types:

A field declared with a type but no explicit field name is called an embedded field. An embedded field 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.

You can't embed a type like map[int]string, that's an anonymous type. Spec requires a type name. Even if you could embed that, it contains brackets which would make it disqualify from being an identifier, and again, spec says the unqualified type name acts as the field name.

Simply create a new type for it which you can then embed:

type mymap map[int]string

type s struct {
    mymap
}

When you embed a type in a struct, you omit the field name. In your second attempt:

type myStruct struct {
    mySlice []int
}

You did not omit the field name (it's mySlice), so this is not embedding, it's a regular, named field.

icza
  • 389,944
  • 63
  • 907
  • 827