gpt4 book ai didi

go - channel 提前终止

转载 作者:数据小太阳 更新时间:2023-10-29 03:42:59 27 4
gpt4 key购买 nike

我正在为每个执行转换的管道制作一系列 go 例程的原型(prototype)。例程在所有数据通过之前终止。

我已经查阅了 Donavan 和 Kernighan 的书并在 Google 上搜索了解决方案。

这是我的代码:

package main

import (
"fmt"
"sync"
)

func main() {
a1 := []string{"apple", "apricot"}

chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string)

var wg sync.WaitGroup

go Pipe1(chan2, chan1, &wg)
go Pipe2(chan3, chan2, &wg)
go Pipe3(chan3, &wg)

func (data []string) {
defer wg.Done()
for _, s := range data {
wg.Add(1)
chan1 <- s
}
go func() {
wg.Wait()
close(chan1)
}()
}(a1)
}

func Pipe1(out chan<- string, in <-chan string, wg *sync.WaitGroup) {
defer wg.Done()
for s := range in {
wg.Add(1)
out <- s + "s are"
}
}
func Pipe2(out chan<- string, in <-chan string, wg *sync.WaitGroup) {
defer wg.Done()
for s := range in {
wg.Add(1)
out <- s + " good for you"
}
}
func Pipe3(in <-chan string, wg *sync.WaitGroup) {
defer wg.Done()
for s := range in {
wg.Add(1)
fmt.Println(s)
}
}


我的预期输出是:

apples are good for you
apricots are good for you

运行main的结果不一致。有时我会得到两条线。有时我只是得到苹果。有时什么都不输出。

最佳答案

正如 Adrian 已经指出的,您的 WaitGroup.Add 和 WaitGroup.Done 调用不匹配。然而,在这种情况下,“我完成了”信号通常是通过关闭输出 channel 给出的。只有在多个 goroutine 之间共享工作时才需要 WaitGroup(即,多个 goroutine 使用相同的 channel ),而这里不是这种情况。

package main

import (
"fmt"
)

func main() {
a1 := []string{"apple", "apricot"}

chan1 := make(chan string)
chan2 := make(chan string)
chan3 := make(chan string)

go func() {
for _, s := range a1 {
chan1 <- s
}

close(chan1)
}()

go Pipe1(chan2, chan1)
go Pipe2(chan3, chan2)

// This range loop terminates when chan3 is closed, which Pipe2 does after
// chan2 is closed, which Pipe1 does after chan1 is closed, which the
// anonymous goroutine above does after it sent all values.
for s := range chan3 {
fmt.Println(s)
}
}

func Pipe1(out chan<- string, in <-chan string) {
for s := range in {
out <- s + "s are"
}

close(out) // let caller know that we're done
}

func Pipe2(out chan<- string, in <-chan string) {
for s := range in {
out <- s + " good for you"
}

close(out) // let caller know that we're done
}

在 Playground 上试试:https://play.golang.org/p/d2J4APjs_lL

关于go - channel 提前终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57594490/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com