2 回答

TA貢獻(xiàn)1846條經(jīng)驗 獲得超7個贊
您的第一個問題是:q <- true
func(c chan bool) {
for _, f := range v {
wg.Add(1)
go f(c)
}
q <- true
}(c)
將其包含在塊中沒有任何作用(我懷疑您在某個時候在go例程中運(yùn)行它)。正如所寫的,它將啟動三個去例程,然后擊中。由于沒有任何東西接收到,這將被阻止。func()q <- trueq
修復(fù)后,您將遇到下一個問題:
p := receive(c, q)
fmt.Println(p)
wg.Wait()
receive從 或 中抓取一些東西;您可能希望從中獲取三個值,然后從中獲取一個值,但它同樣可能(可能更有可能)從之前接收(這會導(dǎo)致另一個死鎖)。vqvqqvwg.Wait
有幾種方法可以解決這個問題;正如彼得在評論中提到的,您可以使用緩沖通道(例如);發(fā)送到被阻止的通道不會阻止,除非該通道已滿?;蛘撸覒岩赡愕囊鈭D是這樣的(游樂場):c := make(chan bool, len(v))
func main() {
v := []func(chan<- bool){
a1,
a2,
a3,
}
q := make(chan bool)
c := make(chan bool)
for _, f := range v {
wg.Add(1)
go f(c)
}
// When the above go routines have completed send to q
go func() {
wg.Wait()
q <- true
}()
p := receive(c, q)
fmt.Println(p)
}
正如彼得所指出的,你確實需要適應(yīng)提前接納和離開的情況。這可以通過使用緩沖通道來解決,或者您可以啟動一個go例程,該例程僅轉(zhuǎn)儲通道上接收的數(shù)據(jù),即:receivefalsev
case v := <-c:
if !v {
fmt.Println("Received ", v)
// Throw away anything else received on v to allow other go routines to complete
go func() { for _ = range v {}}()
return false
}
如果你采取這種方法,你需要確保最終關(guān)閉;事實上,你可以用它作為退出的信號,這可以大大簡化事情:v
go func() {
wg.Wait()
close(c)
}()
這完全消除了對的需求。您的范圍可以通過通道,例如)。qreceivefor v := range c {...

TA貢獻(xiàn)1824條經(jīng)驗 獲得超8個贊
這加起來是英國人的偉大而詳細(xì)的答案。
此示例使用上下文取消來跳過寫入,它總是會耗盡 。c
原始代碼中的問題是,您試圖通過從其出口點停止流來退出,您正在阻礙它。
正如 Brits 的回答所示,這不是停止處理流的正確方法,因為它會在管道中留下非托管數(shù)據(jù)。
一般的想法是在取消信號到達(dá)時停止將數(shù)據(jù)發(fā)送到管道(關(guān)閉輸入數(shù)據(jù)源),并讓管道通過完全耗盡正在進(jìn)行的數(shù)據(jù)來完成其對正在進(jìn)行的數(shù)據(jù)的工作。
package main
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
s := make(chan os.Signal, 10)
signal.Notify(s)
<-s
cancel()
}()
// let us simulate cancellation
go func() {
<-time.After(time.Millisecond * 200)
cancel()
}()
v := []func(context.Context, chan<- bool){
a1,
a2,
a3,
}
c := make(chan bool)
var wg sync.WaitGroup
for _, f := range v {
wg.Add(1)
f := f
go func() {
f(ctx, c)
wg.Done()
}()
}
go func() {
wg.Wait()
close(c)
}()
for v := range c {
fmt.Println("Received ", v)
}
}
func a1(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 1000)
select {
case c <- true:
fmt.Println("Finish 1")
case <-ctx.Done():
fmt.Println("Cancelled 1")
}
}
func a2(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 1000)
select {
case c <- true:
fmt.Println("Finish 2")
case <-ctx.Done():
fmt.Println("Cancelled 2")
}
}
func a3(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 1000)
select {
case c <- true:
fmt.Println("Finish 3")
case <-ctx.Done():
fmt.Println("Cancelled 3")
}
}
最后回答問題標(biāo)題Need to run several func() bool and get the first false
您可能希望實現(xiàn)流減少。捕獲所有值,實現(xiàn)一個小邏輯以盡快關(guān)閉您的減排目標(biāo)。但總是繼續(xù)完全耗盡它。
package main
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
s := make(chan os.Signal, 10)
signal.Notify(s)
<-s
cancel()
}()
// let us simulate cancellation
go func() {
<-time.After(time.Millisecond * 200)
cancel()
}()
v := []func(context.Context, chan<- bool){
a1,
a2,
a3,
}
c := make(chan bool)
var wg sync.WaitGroup
for _, f := range v {
wg.Add(1)
f := f
go func() {
f(ctx, c)
wg.Done()
}()
}
// When the above go routines have completed send to q
go func() {
wg.Wait()
close(c)
}()
firstRes := make(chan bool)
go func() {
var closed bool
for v := range c {
if !v && !closed {
firstRes <- v
closed = true
close(firstRes)
}
fmt.Println("Received ", v)
}
if !closed {
close(firstRes)
}
}()
var wasFalsy bool
for v := range firstRes {
wasFalsy = !v
}
fmt.Println("was falsy ", wasFalsy)
}
func a1(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 2000)
select {
case c <- !true:
fmt.Println("Finish 1")
case <-ctx.Done():
fmt.Println("Cancelled 1")
}
}
func a2(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 2000)
select {
case c <- true:
fmt.Println("Finish 2")
case <-ctx.Done():
fmt.Println("Cancelled 2")
}
}
func a3(ctx context.Context, c chan<- bool) {
<-time.After(time.Millisecond * 2000)
select {
case c <- true:
fmt.Println("Finish 3")
case <-ctx.Done():
fmt.Println("Cancelled 3")
}
}
- 2 回答
- 0 關(guān)注
- 106 瀏覽
添加回答
舉報