我已经制作了一个简单的代码示例来了解管道的用法。
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func1(i, ch1, &wg)
go func2(ch1, ch2)
}
wg.Wait()
close(ch1)
for val := range ch2 {
fmt.Println(val)
}
}
func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Duration(seconds) * time.Second)
fmt.Println(seconds)
ch <- seconds
}
func func2(ch1 chan int, ch2 chan string) {
for range ch1 {
ch2 <- "hello"
}
close(ch2)
}
现在,问题是我没有得到一致的输出(我了解这是一些并发问题,我尚未完全理解)。
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
panic: close of closed channel
goroutine 6 [running]:
main.func2(0xc00006c000, 0xc000056180)
/home/projects/go-tuts/pipeline-loop.go:36 +0x72
created by main.main
/home/projects/go-tuts/pipeline-loop.go:16 +0x10f
exit status 2
另一个人更改了代码(它正在工作),并将func2
放入循环之外,但我希望func2
用于func1
的每次迭代。
因此,我想了解应在何处使用WaitGroup
和close(ch)
?
谢谢。
Temporarya
(golang noobie)
根据用户的回答,我更改了代码,现在我得到了预期的输出(但不是此问题的解决方案),但是仍然存在死锁。 https://play.golang.org/p/O_rp_FLvNh8
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg1 sync.WaitGroup
// var wg2 sync.WaitGroup
for i := 0; i < 3; i++ {
wg1.Add(1)
go func1(i, ch1)
go func2(ch1, ch2, &wg1)
}
for val := range ch2 {
fmt.Println(val)
}
wg1.Wait()
close(ch1)
close(ch2)
}
// func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {
func func1(seconds int, ch chan<- int) {
// defer wg.Done()
time.Sleep(time.Duration(seconds) * time.Second)
fmt.Println(seconds)
ch <- seconds
}
func func2(ch1 chan int, ch2 chan string, wg *sync.WaitGroup) {
defer wg.Done()
for range ch1 {
ch2 <- "hello"
}
}
答案 0 :(得分:1)
您的代码中存在多个问题。
在循环中,您生成了运行Step3_BP2: delta_w_h1 = (X_train)^T * Err_h1
的多(3)个goroutine,并在delta_b_h1 = sum(Err_h1)
中将数据发送到django-djoser
并调用func2
。这是个问题。可能发生的情况是,当一个goroutine将数据sed到func2
时,另一个已关闭该通道,从而导致:
ch2
通常,您不需要多次关闭香奈儿-您只需在它们全部完成后就关闭它们。为此,您需要另一个close(ch2)
;您需要将两个功能都传递给ch2
。
进一步阅读:https://blog.golang.org/pipelines
更新:
我个人使用“作品”模式将数据生成到同一通道,完成所有工作后需要关闭该通道:
panic: close of closed channel
goroutine 6 [running]:
main.func2(0xc00006c000, 0xc000056180)
/home/projects/go-tuts/pipeline-loop.go:36 +0x72
created by main.main
/home/projects/go-tuts/pipeline-loop.go:16 +0x10f
exit status 2
我认为保持API清洁WaitGroup
是个好主意,因为WaitGroup
是关于如何同步工作而不是如何完成工作的。
我已将您的代码更改为以下模式:https://play.golang.org/p/vdCNsxWhgyQ
答案 1 :(得分:1)
我怀疑您只希望一个通道从ch1读取并写入ch2。创建3个go例程来执行相同的操作没有什么意义(而且您最终还会关闭相同的通道多重时间,这会引起叶子bebop指出的恐慌)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func1(i, ch1, &wg)
}
go func2(ch1, ch2)
wg.Wait()
close(ch1)
for val := range ch2 {
fmt.Println(val)
}
}