[日常] 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.一个类型可以自 ...
随机推荐
- strom ui Topology 可视化视图各个指标含义说明
In the visualization, spout components are represented as blue, while bolts are colored between gree ...
- FFmpeg4.0笔记:rtsp2rtmp
Github https://github.com/gongluck/FFmpeg4.0-study.git #include <iostream> using namespace std ...
- git常用命令常用场景
在使用git之前,一直用的是svn版本管理:与svn最大不同的是,git有两个仓库,一个是本地仓库,一个是服务器上共享的仓库:本地仓库是每个开发者自己独有的,即使commit提交也只是提交到本地仓库: ...
- Python地理位置信息库geopy的使用(二):根据中心点坐标,方向,距离计算坐标
上一篇文章我们介绍了geopy的基本使用,这一篇文章我们根据中心点坐标,方向,距中心点距离计算出对应的坐标点,这种用法官网并没有给出详细的文档,我们这里做一下说明 生成坐标点的具体方法 import ...
- AJPFX:外汇的点差和点值
外汇“点差”就是交易商买卖货币之间产生的差值. 要了解点差我们先解释一下“点”的含义:为了精确和方便地表示汇价,一般用5位数字表示,其中最小变化的单位就称为"点".例如:英镑美元货 ...
- .NET Core 常用加密和Hash工具NETCore.Encrypt
前言 在日常开发过程中,不可避免的涉及到数据加密解密(Hash)操作,所以就有想法开发通用工具,NETCore.Encrypt就诞生了.目前NETCore.Encrypt只支持.NET Core ,工 ...
- Spring boot mybatis : Error creating bean with name 'com.github.pagehelper.autoconfigure.MapperAutoConfiguration': Invocation of init method failed;
报错截图: 解决方法: 只能扫描到自定义的mapper,不能扫描到其他文件. @MapperScan("com.streamax.s17.tms.dao.pper.repository&qu ...
- Redis---List(链表)
1. 基本结构 Redis 早期版本存储 list 列表数据结构使用的是压缩列表 ziplist 和普通的双向链表 linkedlist,也就是元素少时用 ziplist,元素多时用 linkedli ...
- @transactional注解,报错后数据库操作回滚失败
1. https://jingyan.baidu.com/article/3a2f7c2e27d51b26afd611ff.html 2. https://blog.csdn.net/lee_star ...
- 【转载】InstallShield 生成安装日志
msiexec.exe /p "C:\Documents and Settings\qa\Desktop\8.3 Patch.msp" /l*v c:\log85gold.log ...