Slice 的用途-作為棧的例子

wilson_yang發表於2018-12-19

遍歷資料夾是一個我們經常遇到的操作,檔案系統是一個樹形結構,我經常喜歡拿這個作為練手例子,比方可以拿來考查遞迴,這個例子是一個遍歷資料夾獲取檔案的函式,沒有使用遞迴,只有20行左右的程式碼。

思路就是用兩個slice來儲存所需的資料,其中一個路徑slice以棧的形式來儲存需遍歷的資料夾,出棧入棧迴圈遍歷資料夾以及子資料夾:

func scanAll(path string) []string {
    var result []string     //結果集
    paths := []string{path} //目錄棧:儲存需要遍歷的資料夾,初始化時傳入需要遍歷的資料夾
    for len(paths) > 0 {    //目錄棧不為空則不斷迴圈
        //出棧pop
        dir := paths[len(paths)-1]
        paths = paths[:len(paths)-1]

        //遍歷pop出的的資料夾
        files, _ := ioutil.ReadDir(dir)
        for _, f := range files {
            p := dir + "/" + f.Name() //拼接路徑
            if f.IsDir() {
                paths = append(paths, p) //如果是資料夾型別則入棧
            } else {
                result = append(result, p) //如果是檔案則存結果
            }
        }
    }
    return result
}

改成遞迴的話可以這麼寫:

func scanAllByRecursive(path string) []string {
    var result, tmp []string //結果集
    files, _ := ioutil.ReadDir(path)
    for _, f := range files {
        p := path + "/" + f.Name()
        if f.IsDir() {
            tmp = scanAllByRecursive(p)
        } else {
            result = append(result, p)
        }
    }
    return append(result, tmp...)
}

還可以這麼寫,把儲存容器放在外部,作為接收器:

type Stack []string
var result Stack
result.scanAllByRecursive(".")

func (result *Stack) scanAllByRecursive(path string) {
    files, _ := ioutil.ReadDir(path)
    for _, f := range files {
        p := path + "/" + f.Name()
        if f.IsDir() {
            result.scanAllByRecursive(p)
        } else {
            *result = append(*result, p)
        }
    }
}

每天進步一點點

相關文章