3

都说 go 简单 小白学完 channel 马上就不会了

 2 years ago
source link: https://www.v2ex.com/t/850955
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Go 编程语言

都说 go 简单 小白学完 channel 马上就不会了

  volvo007 · 11 小时 48 分钟前 · 1842 次点击

到 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, 那就会有 senderreceiver 一对收发的东西 于是我就创建了一个 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 就可以解决. 但是这肯定不是标准做法, 这种情况一般会怎么做呢, 请大佬指教


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK