到 v 上请教下各位大佬. 刚学完 channel 的部分, 就想自己出题考考自己. 任务比较简单, 就是将文件夹下的不同类型的文件移动到对应的子文件夹下面. 例如文件夹 A
包含文件 foo.raw, bar.raw, foo.jpg, bar.jpg
执行后会将 .raw
文件都移动到 raw
文件夹下, 而 .jpg
都会移动到 jpg
文件夹下
我写单线程的还算能搞定, 大体如下
fs, err := ioutil.ReadDir(filepath)
// err 处理略
typeDict := make(map[string]int)
for _, fileinfo := range fs{
slices := strings.Split(fileinfo.Name(), ".")
type := slice[len(slice) - 1]
if _, ok := typeDict[type]; ok {
moveFile()
} else {
createFolder()
moveFile()
typeDict[type] = 1
}
思路比较直白, 就是先获得所有文件信息, 然后遍历获得每个文件的后缀. 如果有同名文件夹, 就把文件挪到这个文件夹里; 如果没有文件夹, 就先创建文件夹然后再移动并打个标记告知已经创建该文件夹 当然会有些边界没有考虑, 比如 文件、文件夹 混合出现, 多级文件夹等情况, 这里先忽略掉
现在想并行执行这个任务, 用 goroutine 和 channel 要怎么完成呢
看完教程, 我的理解是:
既然要用 channel, 那就会有 sender
和 receiver
一对收发的东西
于是我就创建了一个 getInfo
和 一个 dealInfo
函数如下
func getInfo(f []fs.FileInfo, c chan string) {
for _, fs := range f {
if fs.IsDir() || strings.HasPrefix(fs.Name(), ".") {
continue
} else {
c <- fs.Name()
}
}
}
func dealInfo(path string, typeDict map[string]int, c chan string) {
// var name string
for name := range c {
// name = <-c
sp := strings.Split(name, ".")
suffix := sp[len(sp)-1]
if _, ok := typeDict[suffix]; ok {
MoveFile(name, path, suffix)
} else {
CreateFolder(path, suffix)
MoveFile(name, path, suffix)
typeDict[suffix] = 1
fmt.Println(name)
}
}
}
getInfo
不停从切片里面读数据并放到 c
里面, 然后 dealInfo
又不停从 c
里面拿到文件名并作相应的处理. 这看起来 一发一收, 好像没毛病啊, 但是我在 main
里面执行 go getInfo()
和 go dealInfo()
的时候, 怎么文件夹里面什么事情也没发生呢?
我查了一下, 这种情况是子函数还来不及运行主函数就退出导致的. main()
尾部加上一个 time.Sleep
就可以解决. 但是这肯定不是标准做法, 这种情况一般会怎么做呢, 请大佬指教
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.