2012-11-28 12 views
36

मैं सीख रहा हूं और अब तक बहुत प्रभावित हूं। मैंने golang.org पर सभी ऑनलाइन दस्तावेज़ पढ़े हैं और क्रिसनॉल की "द गो प्रोग्रामिंग भाषा वाक्यांश पुस्तिका" के माध्यम से आधा रास्ते पढ़ा है। मुझे चैनलों की अवधारणा मिलती है और लगता है कि वे बेहद उपयोगी होंगे। हालांकि, मुझे रास्ते में कुछ महत्वपूर्ण याद करना होगा, क्योंकि मैं एक तरफा चैनल को बिंदु नहीं देख सकता।गो में एक तरफा चैनल का क्या मतलब है?

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

उत्तर

60

एक केवल पढ़ने के लिए चैनल को केवल पढ़ने के लिए ही पढ़ा जा सकता है, जबकि प्रेषक के पास दो-तरफा चैनल होता है जिस पर वे लिख सकते हैं। उदाहरण के लिए:

func F() <-chan int { 
    // Create a regular, two-way channel. 
    c := make(chan int) 

    go func() { 
     defer close(c) 

     // Do stuff 
     c <- 123 
    }() 

    // Returning it, implicitely converts it to read-only, 
    // as per the function return value. 
    return c 
} 

किससे कभी F() कहता है, एक चैनल है जिस पर वे केवल पढ़ सकते हैं प्राप्त करता है। यह संकलन समय पर एक चैनल के संभावित मिस-उपयोग को पकड़ने के लिए अधिकतर उपयोगी है। क्योंकि पढ़ना/लिखना-केवल चैनल अलग-अलग प्रकार हैं, इसलिए संकलक का उपयोग अपने मौजूदा प्रकार-जांच तंत्र का उपयोग कर सकते हैं ताकि यह सुनिश्चित किया जा सके कि कॉलर सामान को उस चैनल में लिखने की कोशिश नहीं करता है जिसके पास कोई व्यवसाय लेखन नहीं है।

+0

लेकिन प्राप्त करने वाले अंत में, कॉलर इसे दो तरीकों से वापस नहीं ला सकता है? यह वही है जो मैं यहां प्राप्त कर रहा हूं। इसे केवल इसे लौटकर ही रूपांतरित किया जा सकता है? – burfl

+9

आप इसे एक लिखने योग्य संस्करण में परिवर्तित नहीं कर सकते हैं। कंपाइलर शिकायत करेगा कि चैन int टाइप करने के लिए सी (प्रकार <-chan int) को परिवर्तित नहीं किया जा सकता है। ठीक है, आप 'असुरक्षित' पैकेज का उपयोग कर सकते हैं, लेकिन यह पूरी तरह से एक अलग कहानी है। जब यह पैकेज खेल में आता है तो सभी दांव बंद हो जाते हैं। – jimt

3

गो चैनलों को होरेस की संचारिक अनुक्रमिक प्रक्रियाओं पर मॉडलिंग किया गया है, जो एक साथ संगतता के लिए एक प्रक्रिया बीजगणित है जो संचार कलाकारों (छोटे 'ए') के बीच घटना प्रवाह के आसपास केंद्रित है। इस प्रकार, चैनलों की दिशा होती है क्योंकि उनके पास एक प्रेषण अंत होता है और अंत प्राप्त होता है, यानी घटनाओं का निर्माता और घटनाओं का उपभोक्ता। ओकम और लिम्बो में भी इसी तरह का मॉडल उपयोग किया जाता है।

यह महत्वपूर्ण है - डेडलॉक मुद्दों के बारे में तर्क करना मुश्किल होगा यदि किसी चैनल-एंड को मनमाने ढंग से प्रेषक और रिसीवर दोनों अलग-अलग समय में पुन: उपयोग किया जा सकता है।

+0

जोड़ने के लिए धन्यवाद। मुझे यह मूल्यवान लगता है। शायद यह एक नया सवाल होना चाहिए, लेकिन क्या यह एकाधिक प्रेषकों के लिए एक "अंत" और एकाधिक रिसीवर को दूसरे से पढ़ने के लिए सुरक्षित है? – burfl

+0

@burfl - मेरा उत्तर देखें। – tjameson

+0

मुझे नहीं पता कि कई लेखकों या पाठकों को गो चैनलों द्वारा समर्थित किया गया है या नहीं। यहां दिए गए उत्तरों में से एक यह दावा करता है, जबकि भाषा संदर्भ का तात्पर्य है कि यह नहीं है (लेकिन थोड़ा अस्पष्ट है)। यह शायद ही मायने रखता है; इसके विपरीत, जेसीएसपी जावा चैनल लाइब्रेरी एक-से-एक और किसी भी एक चैनल (आदि) के बीच अंतरित है क्योंकि यह * है *, जबकि गो कंपाइलर सिद्धांत रूप से इसे स्वचालित रूप से काम कर सकता है। –

5

मुझे लगता है कि केवल पढ़ने के लिए चैनलों के लिए मुख्य प्रेरणा चैनल के भ्रष्टाचार और आतंक को रोकने के लिए है। कल्पना करें कि क्या आप time.After द्वारा लौटाए गए चैनल को लिख सकते हैं। यह बहुत सारे कोड को गड़बड़ कर सकता है।

इसके अलावा, घबरा हो सकता है यदि आप:

  • एक बंद चैनल

के लिए एक चैनल एक बार

  • लिखने से ज्यादा बंद ये अभियान संकलन समय केवल पढ़ने के लिए चैनलों के लिए त्रुटियाँ हैं , लेकिन जब वे कई go-routines एक चैनल लिख/बंद कर सकते हैं तो वे खराब दौड़ की स्थिति पैदा कर सकते हैं।

    इस के आसपास होने का एक तरीका चैनलों को कभी बंद नहीं करना है और उन्हें कचरा इकट्ठा करना है। हालांकि, close सिर्फ सफाई के लिए नहीं है, लेकिन यह वास्तव में जब चैनल पर लेकर जाता है का उपयोग किया है:

    func consumeAll(c <-chan bool) { 
        for b := range c { 
         ... 
        } 
    } 
    

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

    चूंकि आप केवल-पढ़ने वाले चैनल को बंद नहीं कर सकते हैं, इसलिए यह सही कोड लिखना आसान बनाता है।जैसा कि @jimt ने अपनी टिप्पणी में बताया है, आप एक पठनीय चैनल को केवल एक लिखने योग्य चैनल में परिवर्तित नहीं कर सकते हैं, इसलिए आपको गारंटी है कि किसी चैनल के लिखने योग्य संस्करण तक पहुंच के साथ कोड के केवल कुछ भाग इसे बंद/लिख सकते हैं।

    संपादित करें:

    कई पाठकों होने का सवाल है, यह जब तक आप यह के लिए खाते के रूप में पूरी तरह से ठीक है,। यह विशेष रूप से उपयोगी होता है जब निर्माता/उपभोक्ता मॉडल में उपयोग किया जाता है।

    func produce(l *net.TCPListener, c chan<- net.Conn) { 
        for { 
         conn, _ := l.Accept() 
         c<-conn 
        } 
    } 
    
    func consume(c <-chan net.Conn) { 
        for conn := range c { 
         // do something with conn 
        } 
    } 
    
    func main() { 
        c := make(chan net.Conn, 10) 
        for i := 0; i < 10; i++ { 
         go consume(c) 
        } 
    
        addr := net.TCPAddr{net.ParseIP("127.0.0.1"), 3000} 
        l, _ := net.ListenTCP("tcp", &addr) 
        produce(l, c) 
    } 
    

    संभावना आपके कनेक्शन की हैंडलिंग एक नया कनेक्शन को स्वीकार करने से अधिक समय है, तो आप के बहुत सारे करना चाहते हैं ले जाएगा: उदाहरण के लिए, आप है कि बस कनेक्शन स्वीकार करता है और कार्यकर्ता धागे के लिए एक कतार में उन्हें लिखते हैं एक टीसीपी सर्वर है कहना एक निर्माता के साथ उपभोक्ता। एकाधिक उत्पादक अधिक कठिन होते हैं (क्योंकि आपको चैनल को बंद करने वाले समन्वय की आवश्यकता होती है) लेकिन आप चैनल भेजने के लिए किसी प्रकार का सेमफोर-शैली चैनल जोड़ सकते हैं।

  • +0

    बहुत बहुत धन्यवाद! यहां बहुत सारी अच्छी जानकारी है। मुझे नहीं पता कि यह मूल प्रश्न का उत्तर @jimt से बेहतर है, इसलिए मैं इसे स्वीकार किए गए उत्तर के रूप में छोड़ दूंगा, लेकिन यह टिप्पणियों में मैंने बाद के प्रश्नों को स्पष्ट करने का बहुत अच्छा काम किया है। मैं निश्चित रूप से ऊपर उठाऊंगा। – burfl

    +0

    मुझे स्वीकार्य उत्तर प्राप्त करने की उम्मीद नहीं थी =)। मैंने सोचा कि यह जानकारी उपयोगी होगी। – tjameson

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