我想寫一個這樣的函數:
訪問一個目錄下的所有*.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. 只有一個空間,正好
1. 空間不夠了,加 len 現在2個了
1. 空間又不夠了 ,加len 現在4個了
1. 夠
1. 不夠 加len 8個
1. 夠
1. 夠
1. 夠
內存指針變了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. 只有一個空間,正好
1. 空間不夠了,加 len 現在2個了
1. 空間又不夠了 ,加len 現在4個了
1. 夠
1. 不夠 加len 8個
1. 夠
1. 夠
1. 夠
我猜,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這個功能,只能自己手動記錄文件路徑。
唉,程序算是寫完了吧,如果我上面寫得有什么問題,希望大家指正。