Go使用filepath包Walk函数查找文件时file指针赋值后仍为nil问题
问题原因分析
Go语言中所有函数参数都是值传递,你传入的*os.File类型的file参数本身就是一个指针值,findFile函数接收的是这个指针的副本,后续在闭包中对file变量的赋值,修改的只是副本的指向,完全不会影响example函数中声明的原始file变量,所以调用后原始变量还是nil。这属于代码逻辑错误,该实现思路本身是可行的。
修复方案
方案1:使用二级指针传递
把参数改为二级指针**os.File,通过解引用修改原始变量的指向:
func example() { var file *os.File // 传入file变量的地址,即二级指针 err = filepath.Walk("uploads", findFile(fileId, &file)) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } } func findFile(fileId string, file **os.File) func(path string, info os.FileInfo, err error) error { return func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() && isFileMatching(info.Name(), fileId) { // 解引用二级指针,直接修改外部原始变量的指向 *file, err = os.Open(path) if err != nil { return err } // 可选优化:找到文件后直接终止遍历,避免不必要的目录扫描 return filepath.SkipDir } return nil } }
方案2:用闭包直接捕获外部变量
不需要传递file参数,直接在example函数内定义遍历回调,捕获外部变量,写法更简洁:
func example() { var file *os.File var err error // 直接在内部定义遍历回调,捕获同作用域下的file、fileId变量 walkFunc := func(path string, info os.FileInfo, walkErr error) error { if walkErr != nil { return walkErr } if !info.IsDir() && isFileMatching(info.Name(), fileId) { var openErr error file, openErr = os.Open(path) if openErr != nil { return openErr } return filepath.SkipDir } return nil } err = filepath.Walk("uploads", walkFunc) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } }
内容的提问来源于stack exchange,提问作者doctorsherlock
相关产品推荐
相关产品推荐

