鍍金池/ 問答/GO  Linux/ 在遞歸中,當(dāng)線程數(shù)不定時如何等所有線程都結(jié)束才返回

在遞歸中,當(dāng)線程數(shù)不定時如何等所有線程都結(jié)束才返回

代碼功能

掃描一個文件,如果文件中有-f flist1.f, 那么新打開一個goroutine對flist1.f進(jìn)行掃描, 如果是top.v, 那么直接保存到一個列表里。

代碼

package main

import (
    "bufio"
    "errors"
    "fmt"
    "io"
    "log"
    "os"
    "regexp"
    "strings"
)

type intlist []int

var dlog *log.Logger

type slist struct {
    fn    []string
    count int
}

func main() {
    logFile, err := os.Create("harriszh.log")
    c := make(chan int)
    defer logFile.Close()
    if err != nil {
        log.Fatalln("open file error!")
    }
    dlog = log.New(logFile, "[Debug]", log.Llongfile)
    var s slist
    path := os.Args[1]
    s.getList(path, c)
    i := 0
    for i < s.count {
        <-c
        i++
    }
    s.showdec()
}

func (s *slist) showdec() {
    dlog.Printf("########### BEGIN #################\n")
    for _, k := range s.fn {
        dlog.Printf("%s\n", k)
    }
    dlog.Printf("############# END ###############\n")
}

func (s *slist) getList(path string, c chan int) error {
    scommentRe := regexp.MustCompile(`^\s*(.*?)\s*//.*`)
    //the space is removed by TrimSpace
    flistRe := regexp.MustCompile(`^-f\s+(.*)`)
    fin, err := os.Open(path)
    defer fin.Close()
    if err != nil {
        return errors.New("NOEXIST")
    }
    bufi := bufio.NewReader(fin)
    for {
        lineStat, err := bufi.ReadString('\n')
        if err == io.EOF {
            c <- 1
            break
        }
        if err != nil {
            fmt.Fprintf(os.Stderr, "can't read : %v\n", err)
            os.Exit(1)
        }
        newline := strings.Replace(lineStat, "\n", "", -1)
        linewc := scommentRe.ReplaceAllString(newline, "$1")
        linewc = strings.TrimSpace(linewc)
        if linewc != "" {
            if flistRe.MatchString(linewc) {
                newpath := flistRe.FindStringSubmatch(linewc)[1]
                s.count++
                go s.getList(newpath, c)
            } else {
                s.fn = append(s.fn, linewc)
            }
        }
    }
    return nil
}

測試文件

makefile

TARGET=getlist
SRC = getlist.go

default: build

help:
    @echo "available commands:"
    @echo "    make build"
    @echo "    make run00"
    @echo "    make debug"
    @echo "    make clean"

build:
    go build -gcflags "-N -l" -o ${TARGET} ${SRC}

release:
    go build -ldflags "-s" -o ${TARGET} ${SRC}

#   source /opt/go/src/runtime/runtime-gdb.py
#   set args -input top.v -output out.v
#   b main.main

run run00: 
    ./${TARGET} flist.f


debug: 
    delve ./${TARGET}

clean:
    rm -rf ${TARGET}


.PHONY: clean 

flist.f

test00.v
-f f1.f
//comment0
test01.v
-f f2.f
//no f3.f
-f f3.f

f1.f

test10.v
//comment
test11.v

f2.f

test20.v
test21.v
//comment


## 問題
用了進(jìn)程計數(shù)器,不過問題是還沒等所有進(jìn)程都完,main里面的for i < s.count就開始運(yùn)行了
比較復(fù)雜的方案是把所有讀取的行都通過chan返回,直到?jīng)]有內(nèi)容了
不知道有沒有簡單的方案
回答
編輯回答
撥弦

使用類型sync.WaitGroup,相關(guān)的操作要使用到該類型的Add方法,Done方法,Wait方法。

2018年1月26日 18:40