我刚刚开始。以下是我试图通过以下代码实现的目标。
主要功能为 searchAndLog()创建5个主题。此函数接受一个通道,通过该通道接收目录的路径,它将搜索名为“.DS_Store”的文件,然后对其执行操作。
main函数然后为“文件path.Walk()”创建另一个线程。该线程将传递给它的目录,并且对于它遇到的每个目录(在walkFunc()中),它将执行select语句,将目录路径传递给5个线程之一。
但是当我运行这个程序时,“filepath.Walk()”遇到它的前五个目录将它传递给五个线程,但是一旦它将目录传递给每个线程一次,它停了select中的频道 dir [0] 到目录[5] 将不会再次接受该值。
我做错了什么?
package main
// A simple multithreaded program to calculate how many
// and total disk space occupyed by all ".DS_Store" files.
// It also logs the location of each file along with its
// size
import (
"fmt"
"io/ioutil"
"os"
"flag"
"path/filepath"
)
// Returns true if path is a directory otherwise false
func isDirectory(path string) bool {
file, err := os.Open(path)
if err != nil {
fmt.Println(err)
return false
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
fmt.Println(err)
return false
}
return (fi.Mode()).IsDir()
}
func main() {
// Command line flag to pass in how many threads to swapn
var numThreads int
flag.IntVar(&numThreads, "t", 5, "number of threads")
flag.Parse()
fmt.Println("numThreads: ", numThreads)
// 5 Channels for 5 threads
var dir [5]chan string
for i, _ := range dir {
dir[i] = make(chan string)
}
// This is the function that will be passed to filepath.Walk()
// "select" will be executed only if path points to directory
walkFunc := func(path string, info os.FileInfo, err error) error {
fmt.Println("Visited: ", path)
if isDirectory(path) {
select {
case dir[0] <- path:
fmt.Println("Thread: 1")
case dir[1] <- path:
fmt.Println("Thread: 2")
case dir[2] <- path:
fmt.Println("Thread: 3")
case dir[3] <- path:
fmt.Println("Thread: 4")
case dir[4] <- path:
fmt.Println("Thread: 5")
}
}
return nil
}
// Create 5 threads of searchAndLog()
for i := 0; i < numThreads; i++ {
go searchAndLog(dir[i], i)
}
go filepath.Walk("/Users/nikhil/Workspace", walkFunc)
var input string
fmt.Scanln(&input)
}
// id is passed to identify the thread in the println statements
func searchAndLog(dirpath chan string, id int) {
directory := <- dirpath
fmt.Println("Thread # ", id + 1, directory)
files, _ := ioutil.ReadDir(directory)
for _, f := range files {
if f.Name() == ".DS_Store" {
fmt.Println("Thread # ", id + 1, f.Size())
}
}
}
编辑:正如Damsham指出,线程在接受一次值之后退出。用他建议修复代码的代码替换线程创建循环。
答案 0 :(得分:3)
因为一旦searchAndLog
在频道上收到某些内容,它就会执行其操作并退出。因此,在5个目录之后,所有运行searchAndLog
的goroutine现在都消失了。试试这个:
// Create 5 threads of searchAndLog()
for i := 0; i < numThreads; i++ {
go func(i int) {
for {
searchAndLog(dir[i], i)
}
}(i)
}