fakedu.go 2.0 KB

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