Home > Software design >  how to provide a value for an imported embedded struct literal?
how to provide a value for an imported embedded struct literal?

Time:12-05

noob here :) i'm having trouble understanding

when i do this in one file:

scratch.go

package main

import "fmt"

type foo struct {
    field1 string
    field2 string
}

type bar struct {
    foo
    field3 string
    field4 string
}

func main() {
    fooBar := bar{
        foo{
            "apples",
            "banana",
        },
        "spam",
        "eggs",
    }
    fmt.Printf("%#v\n", fooBar)

}

it works but when i have 3 files like this

rootproject
├── magazine
│   ├── address.go
│   └── employee.go
└── main.go

magazine/address.go

package magazine

type Address struct {
    Street     string
    City       string
    State      string
    PostalCode string
}

magazine/employee.go

package magazine

type Employee struct {
    Name   string
    Salary float64
    Address
}

and main.go

package main

import (
    "fmt"
    "magazine"
)

func main() {
    employee := magazine.Employee{
        Name:   "pogi",
        Salary: 69420,
        magazine.Address{
            Street:     "23 pukinginamo st.",
            City:       "bactol city",
            State:      "betlog",
            PostalCode: "23432",
        },
    }

    fmt.Printf("%#v\n", employee)

}

it's error :(

mixture of field:value and value elements in struct literal

i don't get it, what am i doing wrong? i thought if the struct was nested it is said to be embedded in the outer struct and i can access the the fields of the inner struct from the outer one. which is the case for my first example(the singular file), but when i do it within packages. it's different?

CodePudding user response:

i thought if the struct was nested it is said to be embedded in the outer struct and i can access the the fields of the inner struct from the outer one.

Yes, you can access an embedded field's members directly, however that does not apply when constructing the struct with a composite literal. If you look through the rules for struct literals you'll find this one:

If any element has a key, every element must have a key.

This rule applies regardless of whether a field is embedded or not.


To fix the error you can either remove the other keys:

func main() {
    employee := magazine.Employee{
        "pogi",
        69420,
        magazine.Address{
            Street:     "23 pukinginamo st.",
            City:       "bactol city",
            State:      "betlog",
            PostalCode: "23432",
        },
    }
    fmt.Printf("%#v\n", employee)
}

Or you can specify all the keys:

func main() {
    employee := magazine.Employee{
        Name:   "pogi",
        Salary: 69420,
        Address: magazine.Address{
            Street:     "23 pukinginamo st.",
            City:       "bactol city",
            State:      "betlog",
            PostalCode: "23432",
        },
    }
    fmt.Printf("%#v\n", employee)
}

Note that for an embedded field you can use the type's unqualified name to refer to the embedded field.

https://go.dev/ref/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.

  •  Tags:  
  • go
  • Related