1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- package main
- import (
- "fmt"
- "os"
- "path/filepath"
- "sync"
- )
- // go-fakedu - toy approximation of the du (disk usage)
- // toy program to learn go concurrency structures
- type FileInfo struct {
- path string
- info os.FileInfo
- }
- type SafeArraySlice struct {
- m sync.Mutex
- data []int64
- }
- func NewSafeIntArraySlice() *SafeArraySlice {
- return &SafeArraySlice{
- m: sync.Mutex{},
- data: make([]int64, 100),
- }
- }
- func (a *SafeArraySlice) AppendIntArraySlice(i int64) {
- a.m.Lock()
- defer a.m.Unlock()
- a.data = append(a.data, i)
- }
- func enumFiles(dir string) {
- fileCh := make(chan FileInfo)
- errCh := make(chan error, 1) // Buffered channel to prevent blocking
- var wg sync.WaitGroup
- file_size_storage := NewSafeIntArraySlice()
- // Start a goroutine for walking the file tree
- go func() {
- // Send any errors to the errCh channel
- errCh <- filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !info.IsDir() {
- fileCh <- FileInfo{path, info}
- }
- return nil
- })
- close(fileCh) // Close the fileCh channel after walking is done
- }()
- // Start a goroutine to process files
- go func() {
- for path := range fileCh {
- wg.Add(1)
- go func(fInfo FileInfo) {
- defer wg.Done()
- // Process file (e.g., read, hash, etc.)
- fmt.Println(fInfo.path, fInfo.info.Size())
- file_size_storage.AppendIntArraySlice(fInfo.info.Size())
- }(path)
- }
- wg.Wait()
- close(errCh) // Close the errCh channel after all processing is done
- }()
- // Check for errors from filepath.Walk
- if err := <-errCh; err != nil {
- fmt.Println("Error walking the file tree:", err)
- return
- }
- // Not getting a lock here as by now we know
- // that nothing is currently accessing this slice
- var size int64 = 0
- for _, value := range file_size_storage.data {
- size = size + value
- }
- fmt.Println("Total size: ", float32(size)/(1<<20), "MBs")
- }
- func main() {
- args := os.Args
- if len(args) < 2 {
- fmt.Println("Must provide path to directory")
- os.Exit(1)
- }
- enumFiles(args[1])
- }
|