問題描述:
實(shí)現(xiàn)一個(gè)程序計(jì)算并打印輸入的目錄下所有文件的總數(shù)和總大小(以GB計(jì)算)擂煞。完成之后你將熟悉select伦连、WaitGroup、ioutil的用法袭异。
要點(diǎn):
并發(fā)讀取文件(夾)信息钠龙。
限制開啟的goroutines的最大數(shù)量。
運(yùn)行時(shí)每隔500ms打印當(dāng)前已經(jīng)統(tǒng)計(jì)的文件數(shù)和總大杏濉(使用命令行參數(shù)指定此功能是否啟用)碴里。
拓展:
在執(zhí)行中在有外部輸入時(shí)退出程序。
實(shí)現(xiàn):
import (
? "flag"
? "fmt"
? "io/ioutil"
? "os"
? "path/filepath"
? "sync"
? "time"
)
var verbose = flag.Bool("v", false, "show verbose progress messages")
var sema = make(chan struct{}, 50)
var done = make(chan struct{})
func dirents(dir string) []os.FileInfo{
? select {
? ? ? case sema <- struct{}{}: //
? ? ? case <- done:
? ? ? ? return nil
? }
? defer func() {<- sema}()
? entries, err := ioutil.ReadDir(dir)
? if err != nil{
? ? ? fmt.Fprintf(os.Stderr, "du1: %v\n", err)
? ? ? return nil
? }
? return entries
}
func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64){
? defer n.Done()
? if cancelled(){
? ? ? return
? }
? for _, entry := range dirents(dir){
? ? ? if entry.IsDir(){
? ? ? ? n.Add(1)
? ? ? ? subdir := filepath.Join(dir, entry.Name())
? ? ? ? go walkDir(subdir, n, fileSizes)
? ? ? } else {
? ? ? ? fileSizes <- entry.Size()
? ? ? }
? }
}
func printDiskUsage(nfiles, nbytes int64){
? fmt.Printf("%d files %.1f GB\n", nfiles, float64(nbytes/1e9))
}
func cancelled() bool{
? select {
? case <- done:
? ? ? return true
? default:
? ? ? return false
? }
}
func main() {
? flag.Parse()
? roots := flag.Args()
? var tick <-chan time.Time
? if *verbose{
? ? ? tick = time.Tick(500 * time.Millisecond)
? }
? if len(roots) == 0{
? ? ? roots = []string{"."}
? }
? fileSizes := make(chan int64)
? var nfiles, nbytes int64
? var n sync.WaitGroup
? for _, root := range roots{
? ? ? n.Add(1)
? ? ? go walkDir(root, &n, fileSizes)
? }
? go func() {
? ? ? n.Wait()
? ? ? close(fileSizes)
? }()
? go func() {
? ? ? os.Stdin.Read(make([]byte, 1))
? ? ? close(done)
? }()
loop:
? ? ? for {
? ? ? ? select {
? ? ? ? ? ? case <-done:
? ? ? ? ? ? ? for range fileSizes{
? ? ? ? ? ? ? ? ? //
? ? ? ? ? ? ? }
? ? ? ? ? ? case size, ok := <- fileSizes:
? ? ? ? ? ? ? if !ok {
? ? ? ? ? ? ? ? ? break loop
? ? ? ? ? ? ? }
? ? ? ? ? ? ? nfiles++
? ? ? ? ? ? ? nbytes += size
? ? ? ? ? ? case <- tick:
? ? ? ? ? ? ? printDiskUsage(nfiles, nbytes)
? ? ? ? }
? ? ? }
? printDiskUsage(nfiles, nbytes)
}