我想写一个这样的函数:
访问一个目录下的所有*.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
- 只有一个空间,正好
- 空间不够了,加 len 现在2个了
- 空间又不够了 ,加len 现在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
- 只有一个空间,正好
- 空间不够了,加 len 现在2个了
- 空间又不够了 ,加len 现在4个了
- 够
- 不够 加len 8个
- 够
- 够
- 够
我猜,99.9%的可能是 一个文件夹中有8个.db文件
我去看了一下,还真是。
我想到了两种解决方案:
- 像上面的函数那样改指针(去TMD)
- 返回一个新的切片
最后我选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这个功能,只能自己手动记录文件路径。
唉,程序算是写完了吧,如果我上面写得有什么问题,希望大家指正。
有疑问加站长微信联系(非本文作者)