Tree
The tree package provides a generic tree builder that converts flat slices into hierarchical tree structures.
Quick Start
import "github.com/coldsmirk/vef-framework-go/tree"
type Department struct {
ID string `json:"id"`
ParentID *string `json:"parentId"`
Name string `json:"name"`
Children []Department `json:"children"`
}
// Define the adapter
adapter := tree.Adapter[Department]{
GetID: func(d Department) string { return d.ID },
GetParentID: func(d Department) *string { return d.ParentID },
GetChildren: func(d Department) []Department { return d.Children },
SetChildren: func(d *Department, children []Department) { d.Children = children },
}
// Build tree from flat slice
roots := tree.Build(flatDepartments, adapter)
Adapter
The Adapter[T] struct defines how the tree builder accesses node properties:
type Adapter[T any] struct {
GetID func(T) string // Extract node ID
GetParentID func(T) *string // Extract parent ID (nil = root node)
GetChildren func(T) []T // Get children slice
SetChildren func(*T, []T) // Set children slice
}
Key rules:
- Nodes with
nilparent ID are treated as roots - Nodes whose parent ID references a non-existent node are also treated as roots
- Circular references are protected against via visited tracking
Finding Nodes
FindNode
Search for a node by ID in a tree:
node, found := tree.FindNode(roots, "dept-123", adapter)
if found {
fmt.Println(node.Name)
}
FindNodePath
Get the full path from root to a target node:
path, found := tree.FindNodePath(roots, "dept-456", adapter)
if found {
for _, node := range path {
fmt.Println(node.Name) // prints: "Root" → "Parent" → "dept-456"
}
}
Framework Integration
The tree package is used by the CRUD FindTree builder. When you create a tree endpoint:
crud.NewFindTree[Department, DepartmentSearch](tree.Build)
The framework passes tree.Build as the tree builder function, using the model's tree adapter configuration.