2012-11-12 13 views
10

मैंने भाषा पहले दिन जाना सीखना शुरू कर दिया था। जब मैंने कुछ मजेदार कोड लिखने की कोशिश की, तो मैं एक अजीब व्यवहार से फंस गया।जाने वाली भाषा में रिकर्सिव फ़ंक्शन

package main 

import "fmt" 

func recv(value int) { 
    if value < 0 { 
     return 
    } 

    fmt.Println(value) 
    go recv(value-1) 
} 

func main() { 
    recv(10) 
} 

जब मैं ऊपर कोड चलाने के लिए, केवल 10 छपा है। जब मैं recv पर कॉल करने से पहले go हटा देता हूं, 10 से 0 मुद्रित होते हैं। मेरा मानना ​​है कि मैं यहां नियमित रूप से जाने का दुरुपयोग कर रहा हूं, लेकिन मुझे समझ में नहीं आ रहा है कि यह इस तरह से चलने के लिए क्यों शुरू हुआ।

उत्तर

15

जब मुख्य फ़ंक्शन लौटाता है, तो गो अभी भी मौजूदा गोरोटिन खत्म होने की प्रतीक्षा नहीं करेगा बल्कि इसके बाहर निकलें।

recv पहले "पुनरावृत्ति" के बाद मुख्य पर वापस आ जाएगा और क्योंकि मुख्य में कुछ और करने के लिए कुछ नहीं है, कार्यक्रम समाप्त हो जाएगा। इस समस्या का

एक समाधान के लिए एक चैनल है कि संकेत है कि सब काम हो गया है, निम्नलिखित की तरह है:

package main 

import "fmt" 

func recv(value int, ch chan bool) { 
    if value < 0 { 
     ch <- true 
     return 
    } 

    fmt.Println(value) 
    go recv(value - 1, ch) 
} 

func main() { 
    ch := make(chan bool) 
    recv(10, ch) 

    <-ch 
} 

यहाँ, recv लौटने से पहले एक भी बूलियन भेजेगा और main उस के लिए इंतजार करेंगे चैनल पर संदेश।

प्रोग्राम के तर्क के लिए, इससे कोई फ़र्क नहीं पड़ता कि आप किस प्रकार का विशिष्ट या उपयोग करते हैं। bool और true केवल एक सरल उदाहरण हैं। यदि आप के बजाय chan struct{} का उपयोग करके अधिक कुशल बनना चाहते हैं, तो आपको अतिरिक्त बाइट बचाएगा, क्योंकि खाली structs किसी भी स्मृति का उपयोग नहीं करते हैं।

+4

सिग्नल चैनलों के लिए, जहां चैनल डेटा का प्रकार महत्वपूर्ण नहीं है, तो आप 'चैन स्ट्रक्चर {} 'का उपयोग कर सकते हैं। वांछित व्यवहार की अनुमति देते हुए, एक खाली संरचना में कोई स्मृति नहीं होती है। जबकि एक बूलियन एक बाइट लेता है। – jimt

+1

हाँ, ईमानदार होने के लिए मैं इसे और अधिक जटिल बनाने के लिए एक बूल के लिए गया था। लेकिन हाँ, एक खाली संरचना तकनीकी रूप से बेहतर है। क्या आप इसे मेरे उत्तर में शामिल करना चाहते हैं या क्या मैं इसे स्वयं संपादित करूँगा? :) –

+1

यह आपका उत्तर है, इसके लिए जाएं :) – jimt

10

sync.Waitgroup एक और समाधान है और विशेष रूप से अपने पाठ्यक्रम को चलाने के लिए मनमाने ढंग से गोरोटिन की प्रतीक्षा करने के उद्देश्य से इरादा है।

package main 

import (
    "fmt" 
    "sync" 
) 

func recv(value int, wg *sync.WaitGroup) { 
    if value < 0 { 
     return 
    } 

    fmt.Println(value) 

    wg.Add(1) // Add 1 goroutine to the waitgroup. 

    go func() { 
     recv(value-1, wg) 
     wg.Done() // This goroutine is finished. 
    }() 
} 

func main() { 
    var wg sync.WaitGroup 
    recv(10, &wg) 

    // Block until the waitgroup signals 
    // all goroutines to be finished. 
    wg.Wait() 
} 
-2

मैंने ऐसा किया और भी काम किया। कैसे?

package main 

import "fmt" 

func recv(value int) { 
    if value < 0 { 
     return 
    } 

    fmt.Println(value) 
    recv(value - 1) 
} 

func main() { 
    recv(10) 
} 
+0

क्या आपका दूसरा संस्करण 10,9,8,7,6,5,4,3,2,1 प्रिंट करता था? 100 बार कोशिश करें: डी – vrbilgi

+1

@vrbilgi यह काम नहीं किया। मुझे गलत समझा गया था। धन्यवाद यू। संपादित। ;) – rplaurindo

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