查找 dir 目录下文件名中包含 dst 字符串的文件个数,遇到目录则递归遍历。
最直接的方法:
package main
import (
"fmt"
"io/ioutil"
"strings"
"time"
)
var dst = "main"
var dir = "D:/dev"
var c = 0
// 查找目录树
func main() {
main1()
}
func main1() {
start := time.Now()
search1(dir)
fmt.Println(c)
use := time.Since(start)
fmt.Println(use)
}
func search1(dir string) {
fs, err := ioutil.ReadDir(dir)
if err != nil {
panic(err)
}
for _, f := range fs {
if f.IsDir() {
search1(dir + "/" + f.Name())
} else {
if strings.Contains(f.Name(), dst) {
c++
}
}
}
}
耗时 30 s
找出 1562 个结果
采用 goroutine 优化后
package main
import (
"fmt"
"io/ioutil"
"strings"
"time"
)
var dst = "main"
var dir = "D:/dev"
var c = 0
// 查找目录树
func main() {
main3()
}
var gorCount = 0
var maxGorCount = 30
var haveResult = make(chan bool)
var gorDone = make(chan bool)
var gorStart = make(chan string)
func main3() {
start := time.Now()
gorCount = 1
go search3(dir, true)
waitGor()
fmt.Println(c)
use := time.Since(start)
fmt.Println(use)
}
func waitGor() {
for {
select {
case <-gorDone:
gorCount--
if gorCount == 0 {
return
}
case dirname := <-gorStart:
gorCount++
go search3(dirname, true)
case <-haveResult:
c++
}
}
}
func search3(dir string, gor bool) {
fs, err := ioutil.ReadDir(dir)
if err == nil {
for _, f := range fs {
if f.IsDir() {
if gorCount >= maxGorCount {
search3(dir+"/"+f.Name(), false)
} else {
gorStart <- dir + "/" + f.Name()
}
} else {
if strings.Contains(f.Name(), dst) {
haveResult <- true
}
}
}
} else {
fmt.Println(err)
}
if gor {
gorDone <- true
}
}
耗时为 4s,想你提升 7 倍左右