गोरआउट्स से रिटर्न वैल्यू पकड़ना


83

नीचे दिया गया कोड 'अनपेक्षित चलते' कहते हुए संकलन त्रुटि देता है:

x := go doSomething(arg)

func doSomething(arg int) int{
    ...
    return my_int_value
}

मुझे पता है, अगर गोरोइन का उपयोग किए बिना, मैं फ़ंक्शन को सामान्य रूप से कॉल करता हूं, तो मैं वापसी मूल्य प्राप्त कर सकता हूं। या मैं चैनल आदि का उपयोग कर सकता हूं।

मेरा सवाल यह है कि गोरोइन से इस तरह वापसी मूल्य प्राप्त करना क्यों संभव नहीं है।


7
आप इसे वापस करने के लिए एक चैनल इस्तेमाल कर सकते हैं
rogerdpack

यह गोरोइन के लिए रिटर्न वैल्यू रखने की अनुमति क्यों देता है
श्रीनाथ समला

1
@rogerdpack जो आप उपयोग कर रहे हैं जो भी फ़ंक्शन के एपीआई को बदलने की आवश्यकता है। तो आपको एक रैपर फंक्शन की आवश्यकता हो सकती है अगर यह आपका अपना नहीं है
डेविड कॉलनान

जवाबों:


67

सख्त जवाब यह है कि आप ऐसा कर सकते हैं। यह सिर्फ एक अच्छा विचार नहीं है। यहाँ कोड है कि ऐसा करेगा:

var x int
go func() {
    x = doSomething()
}()

यह एक नए गोरोइन को उगल देगा जो गणना करेगा doSomething()और फिर परिणाम को असाइन करेगा x। समस्या यह है: आप xमूल गोरोइनट से कैसे उपयोग करने जा रहे हैं ? आप शायद यह सुनिश्चित करना चाहते हैं कि स्पॉन्ड गोरोइन इसके साथ किया जाता है ताकि आपके पास दौड़ की स्थिति न हो। लेकिन अगर आप ऐसा करना चाहते हैं, तो आपको गोरोइन के साथ संवाद करने का एक तरीका चाहिए, और यदि आपको ऐसा करने का तरीका मिल गया है, तो क्यों न इसका उपयोग मूल्य वापस भेजने के लिए किया जाए?


6
आप यह सुनिश्चित करने के लिए एक WaitGroup जोड़ सकते हैं कि आप समाप्त कर चुके हैं और इसकी प्रतीक्षा कर रहे हैं। लेकिन जैसा कि आपने कहा, यह सिर्फ ऐसा करने का तरीका नहीं है, एक चैनल है।
Not_a_Golfer

1
यह नहीं है return, यह है assignजाहिर
Nidhin डेविड

95

एक चर को असाइन करने वाले गोरोइन से वापसी मूल्य प्राप्त करना क्यों संभव नहीं है?

गोरोइन (एसिंक्रोनस रूप से) चलाएं और फ़ंक्शन से वापसी रिटर्न अनिवार्य रूप से विरोधाभासी क्रियाएं हैं। जब आप कहते हैं कि goआप "इसे अतुल्यकालिक रूप से करते हैं" या यहां तक ​​कि सरल है: "जाओ! फ़ंक्शन के निष्पादन की प्रतीक्षा न करें"। लेकिन जब आप किसी वैरिएबल पर फंक्शन रिटर्न वैल्यू असाइन करते हैं तो आपको वैरिएबल के भीतर यह वैल्यू मिलने की उम्मीद होती है। इसलिए जब आप ऐसा करते हैं कि x := go doSomething(arg)आप कह रहे हैं: "जाओ, फ़ंक्शन की प्रतीक्षा मत करो! रुको-रुको-रुको! मुझे एक लौटा मूल्य xअगले पंक्ति में नीचे दाईं ओर सुलभ होना चाहिए !"

चैनल

एक गोरआउट से मूल्य प्राप्त करने का सबसे प्राकृतिक तरीका चैनल है। चैनल वे पाइप हैं जो समवर्ती गोरोइनटाइन को जोड़ते हैं। आप एक गोरोइन से चैनल में मान भेज सकते हैं और उन मूल्यों को दूसरे गोरोइन या एक समकालिक समारोह में प्राप्त कर सकते हैं। आप आसानी से उपयोग नहीं कर एक निर्णायक से एक मूल्य प्राप्त कर सकते हैं select:

func main() {

    c1 := make(chan string)
    c2 := make(chan string)

    go func() {
        time.Sleep(time.Second * 1)
        c1 <- "one"
    }()
    go func() {
        time.Sleep(time.Second * 2)
        c2 <- "two"
    }()

    for i := 0; i < 2; i++ {
        // Await both of these values
        // simultaneously, printing each one as it arrives.
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        } 
    }
}

इसका उदाहरण Go By Example से लिया गया है

CSP और संदेश-पासिंग

गो बड़े पैमाने पर सीएसपी सिद्धांत पर आधारित है । ऊपर से अनुभवहीन विवरण को सीएसपी के संदर्भ में सटीक रूप से रेखांकित किया जा सकता है (हालांकि मेरा मानना ​​है कि यह प्रश्न के दायरे से बाहर है)। मैं दृढ़ता से कम से कम सीएसपी सिद्धांत के साथ खुद को परिचित करने की सलाह देता हूं क्योंकि यह आरएडी है। ये छोटे उद्धरण सोच की एक दिशा देते हैं:

जैसा कि इसके नाम से पता चलता है, CSP घटक प्रक्रियाओं के संदर्भ में सिस्टम के विवरण की अनुमति देता है जो स्वतंत्र रूप से काम करते हैं , और संदेश-संचार संचार के माध्यम से पूरी तरह से एक दूसरे के साथ बातचीत करते हैं ।

कंप्यूटर विज्ञान में, संदेश पासिंग एक प्रक्रिया को एक संदेश भेजता है और प्रक्रिया और निर्भर बुनियादी ढांचे का चयन करने और चलाने के लिए वास्तविक कोड का समर्थन करने के लिए निर्भर करता है। संदेश पासिंग पारंपरिक प्रोग्रामिंग से अलग है जहां एक प्रक्रिया, सबरूटीन या फ़ंक्शन को सीधे नाम से आमंत्रित किया जाता है।


9

goकीवर्ड का विचार यह है कि आप doSomething फ़ंक्शन को अतुल्यकालिक रूप से चलाते हैं, और परिणाम के लिए प्रतीक्षा किए बिना वर्तमान गोरआउट जारी रखते हैं, इसके बाद एक 'और' के साथ बैश शेल में कमांड निष्पादित करने की तरह। अगर आप करना चाहते हैं

x := doSomething(arg)
// Now do something with x

तब आपको वर्तमान गोरोइन को ब्लॉक करने की आवश्यकता होती है जब तक कि doSomething खत्म नहीं हो जाता। तो क्यों नहीं वर्तमान goroutine में doSomething कॉल ? अन्य विकल्प हैं (जैसे, doSomething एक चैनल के परिणामस्वरूप परिणाम पोस्ट कर सकता है, जिसे वर्तमान goroutine से मान प्राप्त होता है), लेकिन बस doSomething को कॉल करना और एक चर को परिणाम असाइन करना स्पष्ट रूप से सरल है।


0

यह गो रचनाकारों द्वारा डिजाइन की पसंद है। - वहाँ कपोल-कल्पना / एपीआई की एक पूरी बहुत कुछ async आई / ओ आपरेशन के मूल्य का प्रतिनिधित्व करने के लिए promise, future, async/await, callback, observable-, आदि ये कपोल-कल्पना / एपीआई स्वाभाविक का समय निर्धारण इकाई से जुड़े होते हैं coroutines - और इन कपोल-कल्पना / एपीआई हुक्म कैसे coroutines ( या अधिक सटीक रूप से async I / O का उनके द्वारा प्रतिनिधित्व का वापसी मूल्य) रचा जा सकता है

Async I / O ऑपरेशंस के रिटर्न वैल्यू को दर्शाने के लिए एब्स्ट्रेक्शन / API के रूप में संदेश पासिंग (उर्फ चैनल ) को चुनें। और निश्चित रूप से, गोरोइन और चैनल आपको एसिंक्रोन I / O संचालन को कार्यान्वित करने के लिए एक योग्य उपकरण देते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.