Goroutines。在哪里关闭

问题描述 投票:0回答:1

我正在努力理解我应该在哪里关闭我的通道。

这段代码大约需要0.7秒。

options := [3]string{"0", "1", "2"}
str := fmt.Sprintf("%6d ", id)
for j := 0; j < 40000; j++ {
    str += options[rand.Intn(3)]
}
str += "\n"

添加一个io.Writestring并不会对时间造成影响 所以问题就出在这段代码上

我想要的大概是10万条这样的记录,所以我想放一个goroutine。

func main() {
    file, _ := os.Create("myfile.txt")
    ch := make(chan string)
    for i := 0; i < 100000; i++ {
       go generate(i, ch)
    }

    counter := 0
    for result := range ch {
       counter++
       io.WriteString(file, result)
       if counter == 100000 {
           close(ch)
       }
    }
    file.Close()
}

func generate(id int, c chan string) {
    options := [3]string{"0", "1", "2"}
    str := fmt.Sprintf("%6d ", id)
    for j := 0; j < 40000; j++ {
        str += options[rand.Intn(3)]
    }
    str += "\n"
    c <- str
}

根据我的理解是,我在接收端关闭通道,这不是很理想?另外,这样一来,所有的10万条都应该先发送到goroutine,然后我才能收到任何一条。我可以一边发送请求生成记录,一边开始接收吗?

go concurrency goroutine
1个回答
2
投票

使用计数器来关闭通道并不是一个好的做法。sync.WaitGroup. 这样可以让你更好的控制何时关闭通道。

func main() {

    var wg sync.WaitGroup

    ch := make(chan string)
    file, _ := os.Create("myfile.txt")

    for i := 0; i < 100000; i++ {
        wg.Add(1)

        go func(i int) {
            defer wg.Done()

            options := [3]string{"0", "1", "2"}
            str := fmt.Sprintf("%6d ", i)
            for j := 0; j < 40000; j++ {
                str += options[rand.Intn(3)]
            }
            str += "\n"
            ch <- str
        }(i)
    }

    go func() {
        wg.Wait()
        close(ch)
    }()

    for result := range ch {
        io.WriteString(file, result)
    }
    file.Close()
}

1
投票

看看这是否能解决你的问题...

func main() {
    file, _ := os.Create("myfile.txt")
    ch := make(chan string)
    wg := new(sync.WaitGroup)
    for i := 0; i < 100000; i++ {
       wg.Add(1)
       go generate(i, ch)
    }

    go func(){wg.Wait();close(ch)}()

    counter := 0
    for result := range ch {
       counter++
       io.WriteString(file, result)

    }
    file.Close()
}

func generate(id int, c chan string) {
    options := [3]string{"0", "1", "2"}
    str := fmt.Sprintf("%6d ", id)
    for j := 0; j < 40000; j++ {
        str += options[rand.Intn(3)]
    }
    str += "\n"
    c <- str
    wg.Done()
}
© www.soinside.com 2019 - 2024. All rights reserved.