fakedu.go
1	package main
2
3 import (
4 "fmt"
5 "os"
6 "path/filepath"
7 "sync"
8 )
9
10 // go-fakedu - toy approximation of the du (disk usage)
11 // toy program to learn go concurrency structures
12
13 type FileInfo struct {
14 path string
15 info os.FileInfo
16 }
17
18 type SafeArraySlice struct {
19 m sync.Mutex
20 data []int64
21 }
22
23 func NewSafeIntArraySlice() *SafeArraySlice {
24 return &SafeArraySlice{
25 m: sync.Mutex{},
26 data: make([]int64, 100),
27 }
28 }
29
30 func (a *SafeArraySlice) AppendIntArraySlice(i int64) {
31 a.m.Lock()
32 defer a.m.Unlock()
33 a.data = append(a.data, i)
34 }
35
36 func enumFiles(dir string) {
37 fileCh := make(chan FileInfo)
38 errCh := make(chan error, 1) // Buffered channel to prevent blocking
39 var wg sync.WaitGroup
40
41 file_size_storage := NewSafeIntArraySlice()
42
43 // Start a goroutine for walking the file tree
44 go func() {
45 // Send any errors to the errCh channel
46 errCh <- filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
47 if err != nil {
48 return err
49 }
50 if !info.IsDir() {
51 fileCh <- FileInfo{path, info}
52 }
53 return nil
54 })
55 close(fileCh) // Close the fileCh channel after walking is done
56 }()
57
58 // Start a goroutine to process files
59 go func() {
60 for path := range fileCh {
61 wg.Add(1)
62 go func(fInfo FileInfo) {
63 defer wg.Done()
64 // Process file (e.g., read, hash, etc.)
65 fmt.Println(fInfo.path, fInfo.info.Size())
66 file_size_storage.AppendIntArraySlice(fInfo.info.Size())
67
68 }(path)
69 }
70 wg.Wait()
71 close(errCh) // Close the errCh channel after all processing is done
72 }()
73
74 // Check for errors from filepath.Walk
75 if err := <-errCh; err != nil {
76 fmt.Println("Error walking the file tree:", err)
77 return
78 }
79
80 // Not getting a lock here as by now we know
81 // that nothing is currently accessing this slice
82 var size int64 = 0
83 for _, value := range file_size_storage.data {
84 size = size + value
85 }
86
87 fmt.Println("Total size: ", float32(size)/(1<<20), "MBs")
88 }
89
90 func main() {
91 args := os.Args
92 if len(args) < 2 {
93 fmt.Println("Must provide path to directory")
94 os.Exit(1)
95 }
96
97 enumFiles(args[1])
98 }