मैं गो भाषा सीख रहा हूं। क्या कोई कृपया यहां आउटपुट की व्याख्या कर सकता है?

package main

import "fmt"

var c = make(chan int, 1)

func f() {

    c <- 1

    fmt.Println("In f()")
}

func main() {
    go f()

    c <- 2
    fmt.Println(<-c)
    fmt.Println(<-c)

}

आउटपुट:

In f()
2
1

Process finished with exit code 0

"2" से पहले "इन f ()" क्यों हुआ? यदि "इन f ()" को "2" से पहले प्रिंट किया जाता है, तो बफ़र किए गए चैनल को ब्लॉक कर देना चाहिए। लेकिन ऐसा नहीं हुआ, क्यों?

अन्य आउटपुट उचित हैं।

मेरे भ्रमित करने वाले परिणाम की छवि

go
0
Ivan 30 जिंदा 2020, 17:07
यह मेरी टिप्पणियों से मेल नहीं खाता: यह मेरे लिए 2, In f(), 1 प्रिंट करता है। हालांकि, अगर मैं go f() के बाद देरी जोड़ता हूं तो इसका परिणाम अपेक्षित रूप से गतिरोध में होता है।
 – 
bereal
30 जिंदा 2020, 17:15
 – 
bereal
30 जिंदा 2020, 17:20
1
यह अवरुद्ध नहीं है fmt.Println(<-c) कभी-कभी f() से पहले अलग गोरोइन में हुआ और आपने चैनल को बफर 1 दिया
 – 
Sergii Getman
30 जिंदा 2020, 17:23

2 जवाब

सबसे बढ़िया उत्तर

घटनाओं का क्रम जो इसे चलाने का कारण बनता है वे हैं:

  1. ट्रिगर गोरौटाइन।
  2. चैनल को 2 लिखें। चैनल की क्षमता अब समाप्त हो गई है।
  3. चैनल और आउटपुट परिणाम से पढ़ें।
  4. चैनल को 1 लिखें।
  5. चैनल और आउटपुट परिणाम से पढ़ें।

गतिरोध का कारण बनने वाली घटनाओं का क्रम ये हैं:

  1. ट्रिगर गोरौटाइन।
  2. चैनल को 1 लिखें। चैनल की क्षमता अब समाप्त हो गई है।
  3. चैनल को 2 लिखें। चूंकि चैनल का बफर भरा हुआ है, इसलिए यह ब्लॉक हो जाता है।

आपके द्वारा प्रदान किया गया आउटपुट इंगित करता है कि गोरोइन पहले समाप्त होता है और प्रोग्राम गतिरोध नहीं करता है, जो स्पष्टीकरण के रूप में दो परिदृश्यों से ऊपर है। हालांकि यहां क्या होता है:

  1. ट्रिगर गोरौटाइन।
  2. चैनल को 2 लिखें।
  3. चैनल से 2 पढ़ें।
  4. चैनल को 1 लिखें।
  5. आउटपुट In f()
  6. चैनल से प्राप्त 2 को आउटपुट करें।
  7. चैनल से 1 पढ़ें।
  8. चैनल से प्राप्त 1 को आउटपुट करें।

ध्यान रखें कि जब तक आप उन्हें प्रोग्रामेटिक रूप से लागू नहीं करते हैं, तब तक आपके पास गोरोइन के शेड्यूलिंग से संबंधित कोई गारंटी नहीं है। जब आप एक गोरोइन शुरू करते हैं, तो यह अपरिभाषित होता है जब उस गोरोइन का पहला कोड वास्तव में निष्पादित किया जाता है और तब तक प्रारंभिक कोड कितना आगे बढ़ता है। ध्यान दें कि चूंकि आपका कोड घटनाओं के एक निश्चित क्रम पर निर्भर करता है, यह उस परिभाषा से टूट जाता है, बस स्पष्ट रूप से कहने के लिए।

साथ ही, आपके कार्यक्रम के किसी भी बिंदु पर, अनुसूचक विभिन्न गोरौटाइनों के बीच स्विच करने का निर्णय ले सकता है। यहां तक ​​कि सिंगल लाइन fmt.Printtln(<-c) में भी कई चरण होते हैं और प्रत्येक चरण के बीच में स्विच हो सकता है।

2
Ulrich Eckhardt 30 जिंदा 2020, 18:39
आपके जवाब के लिए धन्यवाद। मुझे लगता है कि f() में रॉडर हैं: 1. चैनल को 1 लिखें। चैनल की क्षमता अब समाप्त हो गई है। 2. प्रिंट "इन एफ ()"। जैसा कि मेरा आउटपुट दिखाता है, मुझे सबसे पहले "इन एफ ()" मिलता है। इस मामले में, मुझे लगता है कि चैनल को "1" लिखा गया है और चैनल समाप्त हो गया है। फिर आउटपुट "2" दिखाता है लेकिन जब यह समाप्त हो जाता है तो मैं चैनल को 2 कैसे लिख सकता हूं। मैं ऐसी स्थिति के बारे में नहीं सोच सकता जब "इन एफ ()" "2" से पहले मुद्रित हो।
 – 
Ivan
30 जिंदा 2020, 18:19
ठीक है, मैं इसे स्पष्ट करने की कोशिश करूंगा।
 – 
Ulrich Eckhardt
30 जिंदा 2020, 18:32
मैं सचमुच आपकी सहायता की सराहना करता हूं। मैं समझ गया। धन्यवाद
 – 
Ivan
30 जिंदा 2020, 19:03

ब्लॉक को पुन: उत्पन्न करने के लिए आपको उस कोड को परीक्षण के साथ करने का सबसे आसान तरीका कई बार चलाना होगा। आपके पास भाग्य का ब्लॉक कारण नहीं है। लेकिन इसकी गारंटी नहीं है:

var c = make(chan int, 1)

func f() {

    c <- 1

    fmt.Println("In f()")
}

func TestF(t *testing.T) {
    go f()

    c <- 2
    fmt.Println(<-c)
    fmt.Println(<-c)

}

और कमांड के साथ चलाएँ:

go test -race -count=1000 -run=TestF -timeout=4s

जहां count परीक्षणों की संख्या। यह मेरे लिए अवरुद्ध पुन: पेश करता है। डिफ़ॉल्ट 10 मिनट प्रतीक्षा न करने के लिए समयबाह्य प्रदान करें

1
Sergii Getman 30 जिंदा 2020, 18:08