🎓 A1Learner
🔍
0 of 34 lessons completed

Go Structs in Depth

Struct embedding places one struct inside another struct without a field name. The fields and methods of the inner struct then read through the outer struct.

An embedded struct promotes its fields and methods

Dog embeds Animal by naming the type alone. The Name field and the Speak method of Animal read through the Dog value.

package main

import "fmt"

type Animal struct {
	Name string
	Legs int
}

func (a Animal) Speak() string {
	return a.Name + " makes a sound"
}

type Dog struct {
	Animal
	Breed string
}

func main() {
	d := Dog{Animal: Animal{Name: "Rex", Legs: 4}, Breed: "Collie"}
	fmt.Println(d.Name)
	fmt.Println(d.Speak())
	fmt.Println(d.Breed)
}

An outer field hides a promoted field

Car embeds Wheels and Engine and adds its own Power field. The name Power reads the outer field, and the full path reads the inner one.

package main

import "fmt"

type Wheels struct {
	Count int
}

type Engine struct {
	Power int
}

type Car struct {
	Wheels
	Engine
	Power int
}

func main() {
	c := Car{Wheels: Wheels{Count: 4}, Engine: Engine{Power: 150}, Power: 200}
	fmt.Println(c.Count)
	fmt.Println(c.Power)
	fmt.Println(c.Engine.Power)
}

An anonymous struct for a one-off shape

A struct type can be written inline where a value is built. The value needs no named type when the shape serves one place.

package main

import "fmt"

func main() {
	point := struct {
		X int
		Y int
	}{X: 3, Y: 5}
	fmt.Println(point.X, point.Y)
	fmt.Println(point.X + point.Y)
}

Struct values compare with ==

Two values of the same struct type compare field by field. Equal fields print true, and one different field prints false.

package main

import "fmt"

type Size struct {
	W int
	H int
}

func main() {
	a := Size{W: 2, H: 3}
	b := Size{W: 2, H: 3}
	c := Size{W: 3, H: 2}
	fmt.Println(a == b)
	fmt.Println(a == c)
}

Example

package main

import "fmt"

type Customer struct {
	Name string
	City string
}

type Order struct {
	Customer
	Item string
	Qty  int
}

func main() {
	o := Order{Customer: Customer{Name: "Hana", City: "Seattle"}, Item: "Pen", Qty: 3}
	fmt.Println(o.Name)
	fmt.Println(o.City)
	fmt.Println(o.Item)
	fmt.Println(o.Qty)
}

Key points

  • An embedded field is written as a type name with no field name of its own.
  • A promoted field is an inner field read through the outer value with one dot.
  • A promoted method is an inner method called on the outer value.
  • An outer field with the same name hides the promoted field of that name.
  • The full path through the inner type name still reaches a hidden field.
  • An anonymous struct is a struct value built without a named type.
  • Two struct values compare with == when all their fields can compare.

In this example, Order embeds Customer and adds Item and Qty. The literal sets the Customer part with its type name. The first print line reads the promoted Name field. The second line reads the promoted City field. The last two lines read the fields of Order itself.

Note

The inner struct keeps its own value inside the outer struct, so one outer value holds both sets of fields.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Go Playground

Exercise

A Dog struct embeds Animal, and Animal has a Name field. The Dog value is named d. Which line prints the promoted Name?