[日常] Go语言圣经-示例: 并发的目录遍历习题
练习 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语言圣经-示例: 并发的目录遍历习题的更多相关文章
- [日常] Go语言圣经--示例: 并发的Clock服务习题
练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结 ...
- [日常] Go语言圣经--示例: 并发的Echo服务
最简单的回声服务器: package main import ( "io" "net" "log" ) func main() { list ...
- [日常] Go语言圣经--包和文件-导入包习题
1.每个包都有一个全局唯一的导入路径 2.按照惯例,一个包的名字和包的导入路径的最后一个字段相同 练习 2.2: 写一个通用的单位转换程序,用类似cf程序的方式从命令行读取参数,如果缺省的话则是从标准 ...
- [日常] Go语言圣经--包和文件-包初始化习题
1.解决包级变量的依赖顺序,然后按照包级变量声明出现的顺序依次初始化 2.包中含有多个.go源文件,它们将按照发给编译器的顺序进行初始化 3.init初始化函数,在每个文件中的init初始化函数,在程 ...
- [日常] GO语言圣经-并发获取多个URL
go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...
- [日常] Go语言圣经前言
https://books.studygolang.com/gopl-zh/ go语言圣经 1.Go语言有时候被描述为“C类似语言”,或者是“21世纪的C语言”. 2.Go语言中和并发编程相关的特性是 ...
- [日常] go语言圣经-声明,变量,赋值,类型,包和文件习题
go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名 ...
- [日常] Go语言圣经-WEB服务与习题
Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...
- [日常] Go语言圣经--接口约定习题
Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...
随机推荐
- C#调用接口注意要点
在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存cookie值,再进行其他接 ...
- CefSharp.v49.0.1浏览器控件完全WPF版,实现禁止弹出新窗口,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接
需求场景:在查询页面,填写查询条件,查询条件包括上传的图片,根据图片的特征查询,这就需要在提交的时候,使用POST提交,因为GET提交无法提交图片数据,提交查询条件之后,在新的窗口展示查询结果.(当然 ...
- WPF 介绍一种在MVVM模式下弹出子窗体的方式
主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...
- 阿里云oss服务通用类
在webconfig中配置信息 <?xml version="1.0" encoding="utf-8"?><configuration> ...
- 操作Checkbox标签
在前端开发中,少不了对Checkbox的操作. 常用的的方法有2个:.is()和.prop()方法.前者是判断 checkbox的状态,选不是未选.而后者为checkbox设置一个值,可以设置chec ...
- 背水一战 Windows 10 (45) - 控件(图标类): IconElement, SymbolIcon, FontIcon, PathIcon, BitmapIcon
[源码下载] 背水一战 Windows 10 (45) - 控件(图标类): IconElement, SymbolIcon, FontIcon, PathIcon, BitmapIcon 作者:we ...
- 201621123018《java程序设计》第12周作业总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...
- CentOS 7修改yum源为阿里源
1.备份本地源 1 # mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 2.获取阿里yum源配置 ...
- 关于scanf、getchar、getch、getche缓冲区分析——C语言
缓冲区 根据数据刷新的时机可以将缓冲区的类型分为:全缓冲.行缓冲.无缓冲 (注意:Windows下的输出设备没有缓冲区,意思是printf是无缓冲的,但是在Linux下printf就是行缓冲的,至于为 ...
- python读取文件首行和最后一行
python读取文件最后一行两种方式 1)常规方法:从前往后依次读取 步骤:open打开文件. 读取文件,把文件所有行读入内存. 遍历所有行,提取指定行的数据. 优点:简单,方便 缺点:当文件大了以后 ...