在递归中,当线程数不定时如何等所有线程都结束才返回

代码功能

扫描一个文件,如果文件中有-f flist1.f, 那么新打开一个goroutine对flist1.f进行扫描, 如果是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


## 问题
用了进程计数器,不过问题是还没等所有进程都完,main里面的for i < s.count就开始运行了
比较复杂的方案是把所有读取的行都通过chan返回,直到没有内容了
不知道有没有简单的方案
回复
阅读 2k
1 个回答

使用类型sync.WaitGroup,相关的操作要使用到该类型的Add方法,Done方法,Wait方法。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏