Fundamentals 6 min read

Understanding Go's Composite Pattern: Building Hierarchical Structures

This article explains the Composite (part‑whole) design pattern in Go, illustrates its concept with natural and file‑system analogies, and provides complete Go code demonstrating how files and folders can be treated uniformly as tree nodes.

Nullbody Notes
Nullbody Notes
Nullbody Notes
Understanding Go's Composite Pattern: Building Hierarchical Structures

Composite Pattern

Objects that have a part‑whole relationship can be organized into a tree hierarchy, allowing clients uniform access to both individual (leaf) and composite (container) objects.

Understanding the Idea

The pattern groups resources that share a relationship into a consistent part‑and‑whole structure. A natural illustration is a leaf: each leaf contains smaller leaflets, which in turn contain finer veins, forming a self‑similar fractal‑like hierarchy.

Another illustration uses a collection of colored pens and shapes; pairing them produces richer colored patterns, showing how combining resources yields more functionality.

Observing a leaf reveals repeated sub‑structures at different scales, exemplifying the self‑similarity that the Composite pattern captures.

Code Demonstration

The example models a file‑system hierarchy, a classic Composite use case.

type Node interface {
    // Add a child node
    Add(child Node)
    // Print the node name with indentation defined by space
    Print(space int)
}

File represents a leaf node; its Add does nothing, while Print outputs the file name with the appropriate indentation.

type File struct {
    name string
}

// Add does nothing for a leaf
func (t *File) Add(child Node) {}

// Print prints the file name with leading spaces
func (t *File) Print(space int) {
    for i := 0; i < space; i++ {
        fmt.Print(" ")
    }
    fmt.Println(t.name)
}

Folder can contain other Node objects. Its Add appends a child to a slice, and Print first prints the folder name, then recursively prints each child with increased indentation.

type Folder struct {
    name  string
    child []Node
}

// Add appends a file or sub‑folder
func (t *Folder) Add(child Node) {
    t.child = append(t.child, child)
}

// Print prints the folder name and then its children
func (t *Folder) Print(space int) {
    for i := 0; i < space; i++ {
        fmt.Print(" ")
    }
    fmt.Println(t.name)
    space++
    for _, v := range t.child {
        v.Print(space)
    }
}

In main, a root folder representing drive D: is created, files and a sub‑folder are added, and the hierarchy is printed.

func main() {
    // Root directory D:
    diver := Folder{name: "D:"}
    // Two files
    f1 := File{name: "1.txt"}
    f2 := File{name: "test.txt"}
    // Sub‑folder with three files
    fd1 := Folder{name: "文档"}
    ff1 := File{name: "2.txt"}
    ff2 := File{name: "3.txt"}
    ff3 := File{name: "4.txt"}
    fd1.Add(&ff1)
    fd1.Add(&ff2)
    fd1.Add(&ff3)
    // Add files and sub‑folder to root
    diver.Add(&f1)
    diver.Add(&f2)
    diver.Add(&fd1)
    // Print the directory tree
    diver.Print(0)
    return
}

The program outputs a hierarchical view of the simulated file system, demonstrating how the Composite pattern enables uniform treatment of individual files and composite folders.

Source code repository:

https://github.com/gofish2020/gopattern/tree/main/structure/composite

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsGoFile SystemTree StructureComposite Pattern
Nullbody Notes
Written by

Nullbody Notes

Go backend development, learning open-source project source code together, focusing on simplicity and practicality.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.