2014-05-10 27 views
11

मैं यूआरएल की सूची पहुंचने योग्य है या नहीं, यह जांचने के लिए गोरोटाइन/चैनल का उपयोग कर रहा हूं। मेरा कोड यहाँ है। ऐसा लगता है कि हमेशा सच हो जाता है। टाइमआउट केस क्यों निष्पादित नहीं हो रहा है? लक्ष्य झूठी वापस जाने के लिए भले ही यूआरएल में से एक से पहुंचा जा सकतागोलांग

import "fmt" 
import "time" 

func check(u string) bool { 
    time.Sleep(4 * time.Second) 
    return true 
} 

func IsReachable(urls []string) bool { 

    ch := make(chan bool, 1) 
    for _, url := range urls { 
     go func(u string) { 
      select { 
      case ch <- check(u): 
      case <-time.After(time.Second): 
       ch<-false 
      } 
     }(url) 
    } 
    return <-ch 
} 
func main() { 
    fmt.Println(IsReachable([]string{"url1"})) 
} 

उत्तर

10

check(u)वर्तमान में सो जाएगा goroutine, यानी func चल रहा है। select कथन केवल लौटने के बाद ही ठीक से चलाया जाता है, और उस समय तक, दोनों शाखाएं चलती हैं और रनटाइम जो भी इसे पसंद कर सकता है उसे चुन सकता है।

आप अभी तक एक और goroutine अंदर check चलाकर इसे हल कर सकते हैं:

package main 

import "fmt" 
import "time" 

func check(u string, checked chan<- bool) { 
    time.Sleep(4 * time.Second) 
    checked <- true 
} 

func IsReachable(urls []string) bool { 

    ch := make(chan bool, 1) 
    for _, url := range urls { 
     go func(u string) { 
      checked := make(chan bool) 
      go check(u, checked) 
      select { 
      case ret := <-checked: 
       ch <- ret 
      case <-time.After(1 * time.Second): 
       ch <- false 
      } 
     }(url) 
    } 
    return <-ch 
} 
func main() { 
    fmt.Println(IsReachable([]string{"url1"})) 
} 

ऐसा लगता है आप URL का एक सेट की गम्यता जाँच करना चाहते हैं, और सच वापसी करता है, तो उनमें से एक उपलब्ध है। यदि समय-समय पर गोरआउटिन को फैलाने के समय की तुलना में लंबी अवधि होती है, तो आप सभी यूआरएल के लिए एक बार टाइमआउट करके इसे सरल बना सकते हैं। लेकिन हम यह सुनिश्चित करें कि चैनल काफी बड़ी सभी चेक करते हैं, या है कि "जीत" नहीं से जवाब धारण करने के लिए है बनाने की जरूरत है हमेशा के लिए अवरुद्ध कर देगा:

package main 

import "fmt" 
import "time" 

func check(u string, ch chan<- bool) { 
    time.Sleep(4 * time.Second) 
    ch <- true 
} 

func IsReachable(urls []string) bool { 
    ch := make(chan bool, len(urls)) 
    for _, url := range urls { 
     go check(url, ch) 
    } 
    time.AfterFunc(time.Second, func() { ch <- false }) 
    return <-ch 
} 
func main() { 
    fmt.Println(IsReachable([]string{"url1", "url2"})) 
} 
+0

धन्यवाद। असल में, मैं पहुंचने योग्य नहीं लौटना चाहता हूं अगर उनमें से कोई पहुंच योग्य नहीं है। इसलिए चेक फ़ंक्शन केवल चैनल के लिए "झूठा" लिख सकता है यदि वह समय-समय पर और यूआरएल तक पहुंचने में विफल रहता है (और यूआरएल तक पहुंचने पर कुछ भी नहीं लिखता)। समय के बाद पूर्ण समय के बाद सत्य लिख सकता है। – Kamal

3

कारण यह हमेशा सच रिटर्न आप अपने select कथन में check(u) बुला रहे हैं है नहीं है। आपको इसे नियमित दिनचर्या के भीतर कॉल करने की आवश्यकता है और फिर परिणाम या टाइमआउट के लिए प्रतीक्षा करने के लिए चयन का उपयोग करें।

यदि आप समानांतर में एकाधिक यूआरएल की पहुंच की जांच करना चाहते हैं तो आपको अपने कोड को पुन: व्यवस्थित करने की आवश्यकता है।

पहले एक समारोह जो एक यूआरएल के गम्यता की जाँच करता है बनाने के लिए:

func IsReachable(url string) bool { 
    ch := make(chan bool, 1) 
    go func() { ch <- check(url) }() 
    select { 
    case reachable := <-ch: 
     return reachable 
    case <-time.After(time.Second): 
     // call timed out 
     return false 
    } 
} 

फिर एक पाश से इस फ़ंक्शन को कॉल करें:

urls := []string{"url1", "url2", "url3"} 
for _, url := range urls { 
    go func() { fmt.Println(IsReachable(url)) }() 
} 

Play

0

परिवर्तन लाइन

ch := make(chan bool, 1) 

ch := make(chan bool) 

के लिए आप एक अतुल्यकालिक (= गैर अवरुद्ध) चैनल खुला था, लेकिन आप एक अवरुद्ध चैनल की आवश्यकता यह काम पाने के लिए।