AFAIK there is nothing ready for this in the standard version of Go.
Tree structures lend themselves well to a recursive approach. I have defined the addFile and addFolder in your file and folder types. Starting from the root folder, you can call these methods in Walk. If you get a / b / c, we will call root.addFile(a, b, c) , a.addFile(b, c) , b.addFile(c) .
I also changed Folder.Folders to a map, because filepath.Walk always gives us full paths, so we can split them and find their components on the folder map.
Here is some quick and dirty code that probably has errors and does not perform full error checking. It only works for the current directory, but this should be easy to fix.
I also added the String () method in the folder, which is recognized by the compiler and will be used when printing instances of the type.
package main import ( "log" "os" "path/filepath" "strings" ) type File struct { Name string } type Folder struct { Name string Files []File Folders map[string]*Folder } func newFolder(name string) *Folder { return &Folder{name, []File{}, make(map[string]*Folder)} } func (f *Folder) getFolder(name string) *Folder { if nextF, ok := f.Folders[name]; ok { return nextF } else { log.Fatalf("Expected nested folder %v in %v\n", name, f.Name) } return &Folder{} // cannot happen } func (f *Folder) addFolder(path []string) { for i, segment := range path { if i == len(path)-1 { // last segment == new folder f.Folders[segment] = newFolder(segment) } else { f.getFolder(segment).addFolder(path[1:]) } } } func (f *Folder) addFile(path []string) { for i, segment := range path { if i == len(path)-1 { // last segment == file f.Files = append(f.Files, File{segment}) } else { f.getFolder(segment).addFile(path[1:]) return } } } func (f *Folder) String() string { var str string for _, file := range f.Files { str += f.Name + string(filepath.Separator) + file.Name + "\n" } for _, folder := range f.Folders { str += folder.String() } return str } func main() { startPath := "." rootFolder := newFolder(startPath) visit := func(path string, info os.FileInfo, err error) error { segments := strings.Split(path, string(filepath.Separator)) if info.IsDir() { if path != startPath { rootFolder.addFolder(segments) } } else { rootFolder.addFile(segments) } return nil } err := filepath.Walk(startPath, visit) if err != nil { log.Fatal(err) } log.Printf("%v\n", rootFolder) }