鍍金池/ 問(wèn)答/GO  網(wǎng)絡(luò)安全/ Golang遞歸函數(shù)怎么實(shí)現(xiàn)并發(fā)?

Golang遞歸函數(shù)怎么實(shí)現(xiàn)并發(fā)?

在開(kāi)發(fā)一個(gè)運(yùn)維管理系統(tǒng)時(shí),一個(gè)模塊中要實(shí)現(xiàn)一個(gè)批量處理并刪除某個(gè)目錄下的每一個(gè)文件的功能。
想法是用遞歸算法遍歷目錄下的子目錄和每一個(gè)文件,在處理每一個(gè)文件的時(shí)候單開(kāi)協(xié)程來(lái)并發(fā)處理。
自己寫了一個(gè)demo,但發(fā)現(xiàn)每次都還沒(méi)處理完目錄下的文件就開(kāi)始刪目錄而導(dǎo)致死鎖。
因?yàn)閯h除目錄的代碼也是在遞歸函數(shù)里面的,所以我不知道該什么時(shí)候從通道里讀數(shù)據(jù)出來(lái)。

刪除并發(fā)的幾行代碼可以單線程正常工作實(shí)現(xiàn)功能,就是不知道怎么搞多并發(fā),大家給個(gè)建議來(lái)討論下唄。

回答
編輯回答
焚音

使用filepath.Glob+ 帶緩沖的channel:

package main

import (
    "fmt"
    "path/filepath"
    "sync"
)

func main() {
    ls, err := filepath.Glob("*") // 獲取頂層文件/文件夾
    CheckErr(err)

    wg := new(sync.WaitGroup)
    ch := make(chan string, 5)

    go DeleteFile(ch, wg)

    for _, v := range ls {
        wg.Add(1)

        ch <- v
    }

    close(ch)

    wg.Wait()
}

func DeleteFile(ch chan string, wg *sync.WaitGroup) {
    for v := range ch {
        fmt.Println("to remove : ", v)
        wg.Done()
    }
}

func CheckErr(err error) {
    if err != nil {
        panic(err)
    }
}
2017年12月13日 06:19
編輯回答
失心人
package segment

import (
    "errors"
    "fmt"
    "io/ioutil"
    "os"
    "path/filepath"
    "sync"
)

func DeleteDir(filedir string) error {
    var w sync.WaitGroup
    filelist, err := ioutil.ReadDir(filedir)
    if err != nil {
        return err
    }
    for _, value := range filelist {
        if value.IsDir() {
            w.Add(1)
            go func(name string) {
                defer w.Done()
                DeleteDir(filepath.Join(filedir, name))
            }(value.Name())
        } else {
            w.Add(1)
            go func(name string) {
                defer w.Done()
                DeleteFile(filepath.Join(filedir, name))
            }(value.Name())
        }
    }
    w.Wait()
    err = os.Remove(filedir)
    if err != nil {
        fmt.Printf("remove file error : %s \n", err.Error())
    }
    return err
}

func DeleteDirAll(filedir string) error {
    if IsDir(filedir) {
        err := DeleteDir(filedir)
        if err != nil {
            fmt.Printf("delete dir failed : %s \n", err.Error())
            return err
        }
        return nil
    } else {
        return DeleteFile(filedir)
    }
}

func DeleteFile(filename string) error {
    if IsExist(filename) {
        return os.Remove(filename)
    }
    return errors.New("file not exist")
}

func IsDir(filename string) bool {
    fi, err := os.Stat(filename)
    if err != nil {
        return false
    }
    if fi == nil {
        return false
    }
    if fi.IsDir() {
        return true
    }
    return false
}

func IsExist(filename string) bool {
    fi, err := os.Stat(filename)
    if err != nil {
        fmt.Printf("file path not exist : %s \n", err.Error())
        return false
    }
    if fi != nil {
        return true
    }
    return false
}
2017年6月4日 17:13