2017-09-30 4 views
8

निम्न कोड 0 प्रिंटिंग रखता है।डेडलॉक प्राप्त करने की कोशिश करते समय शून्य के साथ अनंत लूप

package main 

import (
    "fmt" 
) 

func main() { 

    c := make(chan int) 

    go func() { 
     for i := 0; i < 10; i++ { 
      c <- i // INPUT 
     } 
     close(c) 
    }() 

    for { 
     fmt.Print(<-c) // RECEIVER; OUTPUT 
    } 
} 
मेरी समझ से

, यह 9 करने के लिए 0 प्रिंट चाहिए और फिर एक अनंत लूप पर चलते हैं। यह zero प्रिंटिंग क्यों रखता है?

उत्तर

12

आपकी समझ (लगभग) सही है, सिवाय इसके कि मुख्य goroutine में अनंत लूप ब्लॉक नहीं होगा, लेकिन निरंतर प्राप्त होगा और प्रिंट करेगा।

आपके द्वारा शुरू की गई गोरौटाइन चैनल पर 0, 1, ... 9 भेजती है, तो बंद कर देता है। और एक बंद चैनल से प्राप्त करना ब्लॉक नहीं करता है, इसके विपरीत, यह तुरंत आगे बढ़ सकता है, और यह चैनल के तत्व प्रकार का शून्य मान उत्पन्न करता है, जो 0int प्रकार के लिए है। यह Spec: Receive operator:

nil चैनल ब्लॉक से हमेशा के लिए प्राप्त किया गया है। closed चैनल पर एक प्राप्त ऑपरेशन हमेशा पहले आगे बढ़ सकता है, किसी भी पहले भेजे गए मान प्राप्त होने के बाद तत्व प्रकार zero value प्रदान करना।

तो आप वास्तव में देखते हैं कि आपको क्या करना चाहिए। सबसे पहले यह 0..9 संख्याओं को प्रिंट करता है, फिर 0 प्रिंटिंग बहुत तेज़ (बिना किसी देरी के) रखता है, इसलिए शायद आप प्रारंभिक 0..9 संख्याओं को भी नोटिस नहीं करते हैं।

थोड़ा अपने उदाहरण को संशोधित करने के लिए इतना है कि 15 पुनरावृत्तियों के बाद मुख्य goroutine रास्ते में पाश तत्काल दिखाई देंगे क्या होता है:

c := make(chan int) 
go func() { 
    for i := 0; i < 10; i++ { 
     c <- i // INPUT 
    } 
    close(c) 
}() 

for i := 0; i < 15; i++ { 
    fmt.Print(<-c) // RECEIVER; OUTPUT 
} 

आउटपुट (Go Playground पर यह कोशिश):


हैं एक बार सभी भेजे गए नंबरों को संसाधित (मुद्रित) करने के बाद आपका लक्ष्य छोड़ना है, चैनल पर for range का उपयोग करें:

for i := range c { 
    fmt.Print(i) // RECEIVER; OUTPUT 
} 

यदि आपका लक्ष्य तब तक अवरुद्ध करना है जब तक कि उन 10 संख्याओं को संसाधित न होने पर नई संख्याएं उपलब्ध हों, फिर चैनल बंद न करें। इस तरह अगला प्राप्त ऑपरेशन ब्लॉक होगा। इस मामले में आपके मूल लूप और for range लूप दोनों काम करेंगे, लेकिन for range बेहतर है क्योंकि चैनल बंद होने पर हमेशा बाहर निकलता है।

इस प्रश्न को देखें और चैनल सिद्धांतों को याद रखें: How does a non initialized channel behave?

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