练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。

package main

import (
// "filepath"
"flag"
"fmt"
"io/ioutil"
"os"
"path"
"sync"
"time"
)
/*
练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。
*/ //接收命令行参数-v
var verbose = flag.Bool("v", false, "show verbose progress messages") func main() {
//接收命令行参数,多个路径
flag.Parse()
roots := flag.Args()
//如果没传递任何路径,给默认值
if len(roots) == 0 {
roots = []string{"/"}
} for {
sumFileSize(roots)
time.Sleep(20 * time.Second)
}
} func sumFileSize(roots []string) {
//发送和接收文件字节大小的channel
fileSizes := make(chan int64)
//goroutine的计数器
var n sync.WaitGroup
//循环命令行传递的路径
for _, root := range roots {
n.Add(1)
//启动goroutine计算
go walkDir(root, &n, fileSizes)
}
//启动goroutine,等待所有计算目录的goroutine结束
go func() {
n.Wait()
close(fileSizes)
}()
//定时显示目录进度发送的channel
var tick <-chan time.Time
if *verbose {
tick = time.Tick(500 * time.Millisecond)
}
var nfiles, nbytes int64
//select和loop循环,多路复用
loop:
for {
select {
case size, ok := <-fileSizes:
if !ok {
break loop // fileSizes was closed
}
//计算目录数,计算字节大小
nfiles++
nbytes += size
case <-tick:
//接收到定时channel打印进度
printDiskUsage(nfiles, nbytes)
}
}
//最后打印总计
printDiskUsage(nfiles, nbytes) // final totals
} func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) {
defer n.Done()
for _, entry := range dirents(dir) {
if entry.IsDir() {
n.Add(1)
subdir := path.Join(dir, entry.Name())
//开启多个goroutine进行递归
go walkDir(subdir, n, fileSizes)
} else {
fileSizes <- entry.Size()
}
}
} var sema = make(chan struct{}, 20) // dirents returns the entries of directory dir.
func dirents(dir string) []os.FileInfo {
//使用计数信号量逻辑限制太多并发
sema <- struct{}{}
entries, err := ioutil.ReadDir(dir)
<-sema
if err != nil {
fmt.Fprintf(os.Stderr, "du1: %v\n", err)
return nil
}
return entries
}
func printDiskUsage(nfiles, nbytes int64) {
fmt.Printf("%d files %.1f GB\n", nfiles, float64(nbytes)/1e9)
}

  

[日常] Go语言圣经-示例: 并发的目录遍历习题的更多相关文章

  1. [日常] Go语言圣经--示例: 并发的Clock服务习题

    练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结 ...

  2. [日常] Go语言圣经--示例: 并发的Echo服务

    最简单的回声服务器: package main import ( "io" "net" "log" ) func main() { list ...

  3. [日常] Go语言圣经--包和文件-导入包习题

    1.每个包都有一个全局唯一的导入路径 2.按照惯例,一个包的名字和包的导入路径的最后一个字段相同 练习 2.2: 写一个通用的单位转换程序,用类似cf程序的方式从命令行读取参数,如果缺省的话则是从标准 ...

  4. [日常] Go语言圣经--包和文件-包初始化习题

    1.解决包级变量的依赖顺序,然后按照包级变量声明出现的顺序依次初始化 2.包中含有多个.go源文件,它们将按照发给编译器的顺序进行初始化 3.init初始化函数,在每个文件中的init初始化函数,在程 ...

  5. [日常] GO语言圣经-并发获取多个URL

    go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...

  6. [日常] Go语言圣经前言

    https://books.studygolang.com/gopl-zh/ go语言圣经 1.Go语言有时候被描述为“C类似语言”,或者是“21世纪的C语言”. 2.Go语言中和并发编程相关的特性是 ...

  7. [日常] go语言圣经-声明,变量,赋值,类型,包和文件习题

    go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名 ...

  8. [日常] Go语言圣经-WEB服务与习题

    Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...

  9. [日常] Go语言圣经--接口约定习题

    Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...

随机推荐

  1. 【BZOJ2595】 [Wc2008]游览计划

    BZOJ2595 [Wc2008]游览计划 Solution 考虑这是一个最小费用连通性的问题,既然大家都说这是什么斯坦纳树那就是的吧... 所以我们肯定可以这样设一个dp状态: \(dp_{i,j, ...

  2. 正则表达式中 re.match与re.search的区别

    标签: 本文和大家分享的主要是python正则表达式中re.match函数与re.search方法的相关用法及异同点,希望通过本文的分享,能对大家有所帮助. re.match函数 re.match 尝 ...

  3. ssh登录时在参数中加入密码的解决方案

    在使用ssh登录远程服务器的时候,在执行完ssh user@ip后,要输入登录密码,有时候登录密码记不住,这样以来Ian带来的很多的麻烦,有没有一种在ssh的参数中直接加入密码的方法呢?查看ssh的帮 ...

  4. POJ 2593

    #include <iostream> #include <stdio.h> using namespace std; int cmp ( const void *a , co ...

  5. 06-03 Java 面向对象思想概述、开发设计特征,类和对象的定义使用,对象内存图

    面向对象思想概述.开发设计特征 1:面向对象思想 面向对象是基于面向过程的编程思想. 面向过程:强调的是每一个功能的步骤 面向对象:强调的是对象,然后由对象去调用功能 2:面向对象的思想特点 A:是一 ...

  6. 课程三(Structuring Machine Learning Projects),第一周(ML strategy(1)) —— 1.Machine learning Flight simulator:Bird recognition in the city of Peacetopia (case study)

    []To help you practice strategies for machine learning, the following exercise will present an in-de ...

  7. (转)python高级FTP

    原文地址:http://www.itnose.net/detail/6754889.html高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. ...

  8. c++中double类型控制小数位数

    有时,我们需要输出确定小数位数的double,可以先引入如下头文件: #include <iomanip> 然后通过下列方式输出: double zzz = 8.66666; cout & ...

  9. 基于vue的web应用如何构建成手机端的原生安装包

    话不多说,点击前往

  10. ElasticSearch入门3: Spring Boot集成ElasticSearch

    第一步:创建项目elasticsearch 编写pom文件 <?xml version="1.0" encoding="UTF-8"?> <p ...