मैं जो करना चाहता हूं उसके पास निर्माता गोरौटाइन का एक सेट है (जिनमें से कुछ पूरा हो सकता है या नहीं) और एक उपभोक्ता दिनचर्या है। मुद्दा उस चेतावनी के साथ है जो कोष्ठक में है - हम कुल संख्या को नहीं जानते हैं जो एक जवाब वापस कर देगा।गो में निर्माता/उपभोक्ता के लिए सबसे अच्छा मुहावरे क्या है?
तो मुझे क्या करना चाहते हैं यह है:
package main
import (
"fmt"
"math/rand"
)
func producer(c chan int) {
// May or may not produce.
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
}
func main() {
c := make(chan int, 10)
for i := 0; i < 10; i++ {
go producer(c, signal)
}
// If we include a close, then that's WRONG. Chan will be closed
// but a producer will try to write to it. Runtime error.
close(c)
// If we don't close, then that's WRONG. All goroutines will
// deadlock, since the range keyword will look for a close.
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
fmt.Println("All done.")
}
तो मुद्दा अगर मैं इसे बंद यह गलत है, अगर मैं बंद नहीं करते हैं, है - यह अभी भी गलत है (कोड में टिप्पणियां देखें)।
अब, समाधान एक आउट-ऑफ-बैंड संकेत चैनल होगा, कि सभी उत्पादकों लिखने के लिए:
package main
import (
"fmt"
"math/rand"
)
func producer(c chan int, signal chan bool) {
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
signal <- true
}
func main() {
c := make(chan int, 10)
signal := make(chan bool, 10)
for i := 0; i < 10; i++ {
go producer(c, signal)
}
// This is basically a 'join'.
num_done := 0
for num_done < 10 {
<- signal
num_done++
}
close(c)
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
fmt.Println("All done.")
}
और वह पूरी तरह से जो मैं चाहता करता है! लेकिन मेरे लिए यह एक मुंह की तरह लगता है। मेरा सवाल है: क्या कोई मुहावरे/चाल है जो मुझे कुछ आसान तरीके से करने देती है?
मैं यहाँ एक नज़र था: http://golang.org/doc/codewalk/sharemem/ और यह complete
चान (main
के शुरू में initialised) एक श्रेणी में प्रयोग किया जाता है लेकिन कभी नहीं बंद कर दिया की तरह लगता है। मुझे समझ में नहीं आता कि कैसे।
यदि किसी के पास कोई अंतर्दृष्टि है, तो मैं इसकी सराहना करता हूं। चीयर्स!
संपादित करें: fls0815 जवाब है, और भी कितने करीब-कम चैनल रेंज काम करता है के सवाल का जवाब दे गया है।
काम करने के लिए modifed ऊपर मेरे कोड (पहले fls0815 कृपया आपूर्ति कोड किया):
package main
import (
"fmt"
"math/rand"
"sync"
)
var wg_prod sync.WaitGroup
var wg_cons sync.WaitGroup
func producer(c chan int) {
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
wg_prod.Done()
}
func main() {
c := make(chan int, 10)
wg_prod.Add(10)
for i := 0; i < 10; i++ {
go producer(c)
}
wg_cons.Add(1)
go func() {
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
wg_cons.Done()
}()
wg_prod.Wait()
close(c)
wg_cons.Wait()
fmt.Println("All done.")
}
नमस्ते, आपके उत्तर के लिए धन्यवाद - यह वास्तव में मैं क्या देख रहा था है। क्या आप अपने सुझाव पर विस्तार कर सकते हैं कि 'केवल निर्माता ही चैनल बंद कर दें।' - यह एक सामान्य ज्ञान/कोड-बनाता-भावना नियम की तरह लगता है, लेकिन मैं सोच रहा था कि तकनीकी कारण भी था (क्योंकि आपके द्वारा सूचीबद्ध कोड नमूना चैनल को बंद करने का मुख्य कार्य है)। एक बार फिर धन्यवाद! – Will
मैंने कुछ और जानकारी जोड़ा। HTH। – fls0815
अहह सही, यह समझ में आता है। मैंने सोचा कि शायद यह एक कठिन नियम हो सकता है - जिसमें प्रत्येक निर्माता को यह जांचना होगा कि क्या चैनल को बंद करने की अनुमति है या नहीं (इसलिए इसे बंद करने के लिए आखिरी वाला)। हमारे उदाहरणों में इसे मुख्य() में बंद करने की तुलना में यह स्पष्ट रूप से बहुत गड़बड़ है (अधिक अनावश्यक जांच के साथ), लेकिन मुझे चिंता थी कि यह चीजों को करने का तरीका था (किसी कारण से मुझे अनजान था)। मैं अभी भी शैली के सर्वोत्तम प्रथाओं के लिए एक महसूस करने की कोशिश कर रहा हूं। – Will