go语言在遍历目录的时候删除空目录,一个很奇怪的现象

测试平台:CentOS7.2

代码:

package main

import (

    "os"
    "fmt"
    "path/filepath"

)

func main(){

    path:="/opt/test"
    handlefunc:=func(file_path string , f os.FileInfo , err error) error{
            fmt.Println("I am ",file_path)
            if f.IsDir(){
                    //os.Remove(file_path)
                    //fmt.Println("Empty Dir , deleted !")
            }
            fmt.Println("\n")
            return nil
    }

    fi , _ := os.Stat(path)
    if fi.IsDir(){
            filepath.Walk(path,handlefunc)
    }

}

目录 /opt/test的结构如下

clipboard.png

注意上面的代码有两行被注释掉了,这种情况下我得到了想要的输出:

clipboard.png

然而我把注释打开再运行之后,竟然出现这样的输出:

clipboard.png

【问题】
发现没,空目录'/opt/one/two'被打印了两次,明明第一次被删除了才对,为什么会出现这样的情况???

阅读 4.7k
1 个回答

下面代码是filepath.Walk的实现源码

func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
    // path=/opt/test/one/two  此时运行第一次walkFn,删除目录成功
    err := walkFn(path, info, nil)
    if err != nil {
        if info.IsDir() && err == SkipDir {
            return nil
        }
        return err
    }
    //你写的handle里默认返回nil,所以会继续往下走
    //info为/opt/test/one/two 为目录此处不走
    if !info.IsDir() {
        return nil
    }
    //因为上面已经把two删除,此处读取会失败,err为找不到目录/opt/test/one/two
    names, err := readDirNames(path)
    if err != nil {
        //失败之后又调用了一次你写的hanndel,传入的path还是/opt/test/one/two 这就是第二次的原因。
        return walkFn(path, info, err)
    }

    for _, name := range names {
        filename := Join(path, name)
        fileInfo, err := lstat(filename)
        if err != nil {
            if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
                return err
            }
        } else {
            err = walk(filename, fileInfo, walkFn)
            if err != nil {
                if !fileInfo.IsDir() || err != SkipDir {
                    return err
                }
            }
        }
    }
    return nil
}

从代码看出内部使用的是递归
直接看最底层目录 /opt/test/one/two
walk传入path=/opt/test/one/two
看我给加的代码注释应该就明白了
不明白在问我。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题