2013-04-29 5 views
6

मैं सीख रहा हूं अभी उपयोग कर रहा हूं और मेरी पहली परियोजनाओं में से एक एक साधारण पिंग स्क्रिप्ट है। अनिवार्य रूप से मैं यूआरएल का एक गुच्छा पिंग करना चाहता हूं, और प्रत्येक के जवाब पर XXX सेकंड सेकंड प्रतीक्षा करें और फिर पिंग करें।goroutines के अंदर goroutines लॉन्च कर रहा है स्वीकार्य?

func main() { 
    // read our text file of urls 
    f, err := ioutil.ReadFile(urlFile) 
    if err != nil { 
     log.Print(err) 
    } 

    urlStrings := []string{} 
    urlStrings = strings.Split(string(f), "\n") 

    for _, v := range urlStrings { 
     go ping(v) 
    } 

    // output logs to the terminal 
    // channel is global 
    for i := range c { 
     fmt.Println(i) 
    } 
} 

func ping(url string) { 
    // for our lag timer 
    start := time.Now() 

    // make our request 
    _, err := http.Get(url) 

    if err != nil { 
     msg := url + " Error:" + err.Error() 

     fmt.Println(msg) 

     c <- msg 
     reportError(msg) 
    } else { 
     lag := time.Since(start) 
     var msg string 

     // running slow 
     if lag > lagThreshold*time.Second { 
      msg = url + " lag: " + lag.String() 
      reportError(msg) 
     } 

     msg = url + ", lag: " + lag.String() 
     c <- msg 
    } 

    time.Sleep(pingInterval * time.Second) 
    go ping(url) // is this acceptable? 
} 

मेरी प्राप्त अनुरोध मैं पहले स्थगित res.Body.Close बुला रहा था() लेकिन उसके बाद एप्लिकेशन थोड़ी देर के लिए भाग गया panicing किया गया था: यहाँ संक्षिप्त कोड है। मुझे लगता है कि जब तक goroutine कचरा इकट्ठा नहीं किया गया था तब तक स्थगित प्रतिक्रिया() को प्रतिक्रिया पर कॉल नहीं कर सका और res अब अस्तित्व में नहीं था।

मुझे यह सोचने में मदद मिली कि अगर गोरौटाइन के अंदर एक गोरौटाइन बुलाकर सबसे अच्छा अभ्यास होता है या यदि मैं समारोह को कभी बाहर नहीं निकलता, और फिर एक डिफर को केवल कूरा एकत्र होने के बाद ही बुलाया जाता है।

+0

अन्य goroutines से goroutines spawning कोई समस्या नहीं होनी चाहिए, लेकिन इस मामले में सिर्फ एक लूप का उपयोग न करने का कोई कारण नहीं है? –

+0

@JamesHenstridge I मैं इसे प्रक्रियात्मक लूप में नहीं कर रहा हूं इसलिए मुझे अगली कॉल करने से पहले प्रत्येक अनुरोध को वापस लौटने की प्रतीक्षा नहीं करनी पड़ेगी। मैं समरूपता का उपयोग करने की कोशिश कर रहा हूं ताकि प्रत्येक पिंग चक्र अपने स्वयं के अंतराल के समय पर स्वतंत्र हो। – ARolek

+0

मैं उस हिस्से का जिक्र कर रहा था जहां 'पिंग()' गोरौटाइन बाहर निकलने से ठीक पहले एक और गोरौटाइन पैदा करता है। यदि आप 'पिंग()' के अंदर एक लूप डालते हैं, तो आपको वही प्रभाव मिल जाएगा। –

उत्तर

11

यह ठीक है। एक और goroutine से एक goroutine कॉल करने के लिए यह पूरी तरह से स्वीकार्य है। कॉलिंग गोरौटाइन अभी भी बाहर निकल जाएगी और नया गोरौटाइन इसके सुखद तरीके से चलेगा।

7

एक goroutine के भीतर से एक नया goroutine फैलाना पूरी तरह से ठीक है।

लेकिन मुझे संदेह है कि यह आपके मुद्दे का सबसे सरल और साफ समाधान है। मुझे लगता है कि आपके पहले संस्करण ने स्पष्ट चीज़ की और अंतहीन पाश में प्रत्येक यूआरएल को पिंग किया। और यह काटने defer: फ़ंक्शन लौटने के बाद Defer'ed कॉल निष्पादित की जाती हैं। (इसमें एक गोरौटाइन मधुमक्खियों को समझने के लिए कुछ भी नहीं है "कचरा इकट्ठा किया जाता है; वास्तव में गोरौटाइन्स सिर्फ समाप्त होता है, एकत्र नहीं किया जाता है)। अंतहीन पाश में आप कभी वापस नहीं आते हैं, आप केवल उन कॉलों को जमा करते हैं जिन्हें कभी निष्पादित नहीं किया जाता है। इस प्रकार आप सभी खुले बंद नहीं होते res.Body और आप स्मृति/जो कुछ भी और एक आतंक को देखने से बाहर चलाने के।

कर defer res.Body.Close एक अच्छा मुहावरा है, लेकिन नहीं एक अंतहीन लूप के अंदर।

मैं अपने पहले संस्करण कोशिश करते हैं और सीधे res.Body पर अमल होगा । शून्य त्रुटि पथ पर लिखें।

+0

अगर मैं res.Body.Close() को कॉल नहीं करता हूं तो मेमोरी उपयोग परिसर भी होगा, या फिर रद्द कर दिया जाएगा? – ARolek

+0

आपको ** ** res.Body.Close कॉल करना होगा। यह किसी कारण से दस्तावेज है। (आपका कोड अन्यथा रिसाव करेगा।) – Volker

+0

क्या होगा अगर मैं इसे एक var के रूप में नहीं कर सकता जैसा कि मैं ऊपर कर रहा हूं? _, गलती: = http.Get (url) वह रिसाव होगा? – ARolek

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