2012-12-28 9 views
7

मैं गो सीख रहा हूं और GoTours से this lesson पर काम कर रहा हूं। यहां तक ​​कि मेरे पास अभी तक क्या है।मैं चैनल डेडलॉकिंग के अपवाद को कैसे पकड़ूं?

package main 

import (
    "fmt" 
    "code.google.com/p/go-tour/tree" 
) 

// Walk walks the tree t sending all values 
// from the tree to the channel ch. 
func Walk(t *tree.Tree, ch chan int) { 
    if t != nil { 
     Walk(t.Left, ch) 
     ch <- t.Value 
     Walk(t.Right, ch) 
    } 
} 

func main() { 
    var ch chan int = make(chan int) 
    go Walk(tree.New(1), ch) 
    for c := range ch { 
     fmt.Printf("%d ", c)  
    } 
} 

जैसा कि आप देख, मैं मान मैं एक चैनल में लिखा प्रिंट के आधार पर अपने वॉक समारोह का परीक्षण करने का प्रयास करें। हालांकि, मुझे निम्न त्रुटि मिलती है।

1 2 3 4 5 6 7 8 9 10 throw: all goroutines are asleep - deadlock! 

goroutine 1 [chan receive]: 
main.main() 
    main.go:25 +0x85 

goroutine 2 [syscall]: 
created by runtime.main 
    /usr/local/go/src/pkg/runtime/proc.c:221 

exit status 2 

यह त्रुटि उम्मीद की जानी चाहिए मुझे लगता है कि क्योंकि मैं कभी close चैनल। हालांकि, क्या कोई तरीका है कि मैं इस डेडलॉक त्रुटि को "पकड़" सकता हूं और प्रोग्रामेटिक रूप से इसका सामना कर सकता हूं?

+2

परिभाषा के अनुसार, एक गतिरोध मतलब है कि सभी goroutines दौड़ नहीं रहे हैं यदि कुछ भी नहीं चल रहा है, तो कोई गोरौटाइन नहीं है जो अपवाद को "पकड़" सकता है। – newacct

+0

धन्यवाद! यदि ऐसा है, तो क्या मैं एक तरीका है जिसे मैंने चैनल से पढ़ना बंद कर दिया है, जब मैंने 'n' बार पढ़ा है, जहां' n' चैनल में मैंने कितनी बार लिखा है? – dangerChihuahua007

+2

एक और युक्ति: वाक फ़ंक्शन में चैनल दिशा निर्दिष्ट करना अच्छा अभ्यास है, यानी func Walk (t * tree.Tree, ch chan <- int) –

उत्तर

6

डेडलॉक एक नील पॉइंटर डिफरेंस के समान है जो आपके प्रोग्राम में एक बीयूजी का प्रतिनिधित्व करता है। त्रुटि के इस वर्ग को आमतौर पर इस कारण से पुनर्प्राप्त करने योग्य नहीं है।

जैसा कि एलबीएनएन ने उल्लेख किया है, यहां समस्या यह है कि आपको अपने चैनल को "बंद करें (myChan)" करने की आवश्यकता है। यदि आप यह रेंज लूप नहीं करते हैं, तो लूप अगले तत्व के लिए हमेशा के लिए इंतजार करेगा।

आप कुछ इस तरह की कोशिश कर सकते हैं: आप समानांतर में पेड़ आप और परिवर्तन करने की आवश्यकता होगी पार करने के लिए चाहते हैं

func main() { 
    var ch chan int = make(chan int) 
    go func() { 
     Walk(tree.New(1), ch) 
     close(ch) 
    }() 
    for c := range ch { 
     fmt.Printf("%d ", c) 
    } 
} 

:

package main 

import (
    "code.google.com/p/go-tour/tree" 
    "fmt" 
    "sync" 
) 

// Walk walks the tree t sending all values 
// from the tree to the channel ch. 
func Walk(t *tree.Tree, ch chan int, done *sync.WaitGroup) { 
    if t != nil { 
     done.Add(2) 
     go Walk(t.Left, ch, done) //look at each branch in parallel 
     go Walk(t.Right, ch, done) 
     ch <- t.Value 
    } 
    done.Done() 
} 

func main() { 
    var ch chan int = make(chan int, 64) //note the buffer size 
    go func() { 
     done := new(sync.WaitGroup) 
     done.Add(1) 
     Walk(tree.New(1), ch, done) 
     done.Wait() 
     close(ch) 
    }() 
    for c := range ch { 
     fmt.Printf("%d ", c) 
    } 
} 
5

नहीं, आप डेडलॉक से ठीक नहीं हो सकते हैं।

+1

धन्यवाद! लेकिन फिर, मैं चैनल में भेजे गए आइटम को कैसे प्रिंट करूं? – dangerChihuahua007

7

यह डेडलॉक्स क्योंकि range चैनल बंद होने तक पुनरावृत्तियों का निर्माण करता है। http://golang.org/ref/spec#For_statements

यहाँ आप या तो चैनल बंद करते हैं पेड़ पूरी तरह से पता लगाया जाता है या किसी अन्य के निर्माण का उपयोग करने की जरूरत है।

इस उदाहरण के लिए, आप जानते हैं कि पेड़ आकार 10 के हैं, इसलिए आप केवल 1 से 10 तक लूप के लिए एक कर सकते हैं और एक बार प्रत्येक पुनरावृत्ति पर चैनल से पढ़ सकते हैं।

संबंधित मुद्दे