Golang 递归访问目录与函数修改数组的问题

送你一碗大麦茶 · · 962 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

我想写一个这样的函数:
访问一个目录下的所有*.db文件。并放入filepath[]中。filepath是一个结构体:

type filepath struct {
    fullpath string   //文件路径名
    filename string //文件名
}

写完了的程序是这个样子的,打印时:

package main

import (
    "io/ioutil"
    "strings"
    "path"
)

const rootpath string = "D://testfile/2345"

type filepath struct {
    fullpath string
    filename string
}

func main() {
    var files []filepath
    files = make([]filepath, 0, 1)
    //dir,_:=ioutil.ReadDir(rootpath)
    //递了个归
    readdir(rootpath, files)
    for _, v := range files {
        println(v.filename, v.fullpath)
    }
}

func readdir(dirs string, files []filepath) {

    dir, _ := ioutil.ReadDir(dirs)
    for _, v := range dir {
        if v.IsDir() {
            dir2 := path.Join(dirs, v.Name())
            readdir(dir2, files)
        } else {
            if strings.HasSuffix(v.Name(), ".db") {
                var str string = v.Name()
                files = append(files, filepath{fullpath: path.Join(dirs, str), filename: str})
            }
        }
    }
}
//输出:

(什么~~都没有 一脸懵b.jpg)

像我这种JB型boy(脚本型语言boy)不常用指针就会有这种错误。加点信息调试下?

//把最后一个else 里加两句,变成下面的:
else {
            if strings.HasSuffix(v.Name(), ".db") {
                str  := v.Name()
                println("老地址", files)
                files = append(files, filepath{fullpath: path.Join(dirs, str), filename: str})
                println("新地址", files)
                //println(len(files) )
            }
//输出如下(一对一对看还是很方便  []里的数字含义为 [len/cap]):
老地址 [0/1]0xc042033f58
新地址 [1/1]0xc042033f58
老地址 [1/1]0xc042033f58
新地址 [2/2]0xc042054b00
老地址 [2/2]0xc042054b00
新地址 [3/4]0xc042066b00
老地址 [3/4]0xc042066b00
新地址 [4/4]0xc042066b00
老地址 [4/4]0xc042066b00
新地址 [5/8]0xc042036300
老地址 [5/8]0xc042036300
新地址 [6/8]0xc042036300
老地址 [6/8]0xc042036300
新地址 [7/8]0xc042036300
老地址 [7/8]0xc042036300
新地址 [8/8]0xc042036300

分析下,按照append的尿性,每次内存不够就添加 len的空间,会不会生成一段时的内存,重新分配给指针???
先确认下会不会分配吧!!!!
一共是八个append

  1. 只有一个空间,正好
  2. 空间不够了,加 len 现在2个了
  3. 空间又不够了 ,加len 现在4个了
  4. 不够 加len 8个

内存指针变了3次,那么,就可以肯定,一开始的files = make([]filepath, 0, 1) 应该有第一组数据啊~
再打印下内存,println换下位置

func main() {
    var files []filepath
    files = make([]filepath, 0, 1)
    //dir,_:=ioutil.ReadDir(rootpath)
    //递了个归
    println("老地址", files)
    readdir(rootpath, files)
    for _, v := range files {
        println(v.filename, v.fullpath)
    }
}

func readdir(dirs string, files []filepath) {
    println("新地址", files)
    dir, _ := ioutil.ReadDir(dirs)
    for _, v := range dir {
        if v.IsDir() {
            dir2 := path.Join(dirs, v.Name())
            readdir(dir2, files)
        } else {
            if strings.HasSuffix(v.Name(), ".db") {
                str  := v.Name()
                files = append(files, filepath{fullpath: path.Join(dirs, str), filename: str})
                //println(len(files) )
            }
        }
    }
}
//打印信息如下:
老地址 [0/1]0xc042033f58
新地址 [0/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58
新地址 [1/1]0xc042033f58

我发现,头指针依旧是那个头指针,所以结论:
随着append增加,头指针依旧是那个头指针
那么问题来了,为什么就是打印不出来!!!
难道,append有坑,加的东西没有给上?
写个小程序试试吧。

package main

func main() {
    var  p1 []int=[]int{1,2,3,4,5}
    change(p1)
    println(p1[5])
}
func change(p1 []int) {
    p1=append(p1,2222)
}
//输出
panic :数组越界

此时,我真的是。。。。
我突然想到了什么东西!!!!
突然明白过来,p1是个切片, main中的p1始终指向 {1,2,3,4,5} 而不会指向{1,2,3,4,5,2222 }
程序修改如下:

package main

func main() {
    var  p1 []int=[]int{1,2,3,4,5}
    change2(&p1)
    println(p1[5])
}
func change2(p1 *[]int) {
    *p1=append(*p1,2222)
}
//输出: 2222

到这里,我又有了一想到了前面近乎完美的调试信息,就是这一段:

分析下,按照append的尿性,每次内存不够就添加 len的空间,会不会生成一段时的内存,重新分配给指针???
先确认下会不会分配吧!!!!
一共是八个append

  1. 只有一个空间,正好
  2. 空间不够了,加 len 现在2个了
  3. 空间又不够了 ,加len 现在4个了
  4. 不够 加len 8个

我猜,99.9%的可能是 一个文件夹中有8个.db文件 我去看了一下,还真是。
我想到了两种解决方案:

  1. 像上面的函数那样改指针(去TMD)
  2. 返回一个新的切片

最后我选2,别人看起来也方便点,于是,整个程序就变成:

package main

import (
    "io/ioutil"
    "strings"
    "path"
)

const rootpath string = "D://testfile/2345"


type filepath struct {
    fullpath string
    filename string
}

func main() {
    var files []filepath
    files = make([]filepath, 0, 1)
     files= readdir(rootpath, files)
    for _, v := range files {
        println(v.filename, v.fullpath)
    }
}

func readdir(dirs string, files []filepath) []filepath {
    dir, _ := ioutil.ReadDir(dirs)
    for _, v := range dir {
        if v.IsDir() {
            dir2 := path.Join(dirs, v.Name())
             files=readdir(dir2, files)
        } else {
            if strings.HasSuffix(v.Name(), ".db") {
                str  := v.Name()
                files = append(files, filepath{fullpath: path.Join(dirs, str), filename: str})
                //println(len(files) )
            }
        }
    }
    return files
}

再说一下go 的 path吧,感觉功能有点少,并没有 go.getpath这个功能,只能自己手动记录文件路径。
唉,程序算是写完了吧,如果我上面写得有什么问题,希望大家指正。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:送你一碗大麦茶

查看原文:Golang 递归访问目录与函数修改数组的问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

962 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传