Struct Embedding Is Better with Go 1.27

2026/09/16

Go gopher

Go 1.27’s new struct literal field behavior can make code using embedded structs a little cleaner

A common pattern when representing entities is to pull the fields every entity shares into a base struct and embed it:

type Entity struct {
    ID        uuid.UUID
    CreatedAt time.Time
    UpdatedAt time.Time
}

type User struct {
    Entity

    Name  string
    Email string
}

Since Entity is embedded, you can already access its fields directly:

func WelcomeUser(user User) {
    // using user fields
    fmt.Printf("Welcome, user #%s! You joined at %s.\n", user.ID, user.CreatedAt.Format(time.Kitchen))
}

But before Go 1.27, when creating a struct literal, promoted fields couldn’t be used directly as keys

You had to write:

// we need to set Entity nested, or assign its fields separately
user := User{
    Entity: Entity{
        ID: uuid.New(),
    },
    Name:  "Gopher",
    Email: "gopher@gogogo.com",
    //...
}

With Go 1.27, you can write:

user := User{
    ID:    uuid.New(), // the ID field got promoted from Entity to our User, we can set at initialization!
    Name:  "Gopher",
    Email: "gopher@gogogo.com",
    //...
}

The interesting part is that ID isn’t actually declared directly inside User. It’s a promoted field from the embedded Entity

This is a small language change, but it makes embedded structs much nicer to initialize, especially in codebases that rely heavily on composition to model entities.

The data used here is only for example purposes, if you use an ORM like GORM, ID, CreatedAt and UpdatedAt would probably be set automatically once you embed gorm.Model

As a bonus, uuid is also new in Go 1.27: it’s now part of the standard library, so uuid.New() here needs no third-party import! :)