गोरूटीन प्रबंधन
गोरूटीन वजनमान होती हैं, लेकिन वे मुफ्त नहीं होतीं: कम से कम, वे स्टैक और सीपीयू शेड्यूलिंग के लिए मेमोरी खपत करती हैं। हालांकि इन लागतों को गोरूटीन का उपयोग करने के लिए छोटा माना जा सकता है, बड़ी मात्रा में उन्हें नियंत्रित जीवनकाल के बिना उत्पन्न करना गंभीर प्रदर्शन समस्याओं में ले जा सकता है। अनियंत्रित जीवनकाल वाली गोरूटीन और अन्य समस्याओं की भी ओर जा सकती हैं, जैसे कि अपरिचित ऑब्जेक्ट्स को संकलित करने से रोकना और अपरिचित संसाधनों को संरक्षित करना।
इसलिए, अपने कोड में गोरूटीन लीक न करें। गोरूटीन लीक के लिए go.uber.org/goleak का उपयोग करें। जो पैकेज गोरूटीन पैदा कर सकते हैं, उनकी गोरूटीन लीक का परीक्षण करने के लिए।
सामान्यत: हर गोरूटीन के पास :
- एक संकेतिय बंद होने का निर्धारण; या
- गोरूटीन को संकेत करने का कोई तरीका होना चाहिए।
दोनों मामलों में, कोड के लिए ब्लॉक और गोरूटीन के पूरा होने की प्रतीक्षा करने का एक तरीका होना चाहिए।
उदाहरण के लिए:
सिफारिश नहीं की जाती:
go func() {
for {
flush()
time.Sleep(delay)
}
}()
// इस गोरूटीन को रोकने का कोई तरीका नहीं है। यह लागूशस्त्र समाप्ति तक अनियंत्रित रूप से चलेगा।
सिफारिश की जाती है:
var (
stop = make(chan struct{}) // गोरूटीन को रोकने के लिए संकेत करें
done = make(chan struct{}) // इसका अर्थ है कि गोरूटीन समाप्त हो गई है
)
go func() {
defer close(done)
ticker := time.NewTicker(delay)
defer ticker.Stop()
for {
select {
case <-ticker.C:
flush()
case <-stop:
return
}
}
}()
// ... अन्य कोड
close(stop) //इसका अर्थ है कि गोरूटीन को रोकने के लिए संकेत करें
<-done // और इसकी समाप्ति का इंतजार करें
// इस गोरूटीन का समाप्ति हो सकता है बंद करके ,और हम इसकी समाप्ति का इंतजार कर सकते हैं <-done।
गोरूटीन्स की समाप्ति का इंतजार
सिस्टम द्वारा उत्पन्न गोरूटीन को इंतजार करने का एक तरीका होना चाहिए। इसको प्राप्त करने के दो सामान्य तरीके होते हैं:
-
sync.WaitGroup
का उपयोग करना। इस तरीके का उपयोग तब करें जब विभिन्न गोरूटीन के इंतजार करने हो।
var wg sync.WaitGroup
for i := 0; i < num; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// ...
}()
}
wg.Wait()
- एक अविभाज्य
chan struct{}
जोड़ना, और उसे बंद करना जब गोरूटीन पूर्ण हो जाए। इस तरीके का उपयोग तब करें जब केवल एक गोरूटीन हो।
done := make(chan struct{})
go func() {
defer close(done)
// ...
}()
// गोरूटीन की पूर्णता का इंतजार करने के लिए:
<-done
init()
फ़ंक्शन को गोरूटीन नहीं बनाना चाहिए। इसके अलावा, init() का उपयोग न करें।
अगर किसी पैकेज को परिचालन गोरूटीन की आवश्यकता होती है, तो उसमें गोरूटीन के जीवनकाल को प्रबंधित करने के लिए जिम्मेदार एक ऑब्जेक्ट प्रकट किया जाना चाहिए। इस ऑब्जेक्ट को गोरूटीन के पूर्ण होने का संकेत देने के लिए (बंद करें
, रोकें
, बंद करें
, आदि) एक विधि प्रदान करनी चाहिए।
सिफारिश की जाती नहीं:
func init() {
go doWork()
}
func doWork() {
for {
// ...
}
}
// जब उपभोक्ता इस पैकेज को निर्यात करता है, तो एक पृष्ठभूमि गोरूटीन संयुक्त रूप से उत्पन्न होती है। उपभोक्ता गोरूटीन को नियंत्रित नहीं कर सकता और नहीं इसे बंद कर सकता।
सिफारिश की जाती है:
type Worker struct{ /* ... */ }
func NewWorker(...) *Worker {
w := &Worker{
stop: make(chan struct{}),
done: make(chan struct{}),
// ...
}
go w.doWork()
}
func (w *Worker) doWork() {
defer close(w.done)
for {
// ...
select {
case <-w.stop:
return
}
}
}
// शटडाउन यह कहता है कि कार्यकर्ता को रोकें
// और इसकी पूर्णता का इंतजार करता है।
func (w *Worker) Shutdown() {
close(w.stop)
<-w.done
}
उपभोक्ता द्वारा अनुरोध किए जाने पर कार्यकर्ता केवल उत्पन्न किए जा सकते हैं, और उपभोक्ता द्वारा प्रयुक्त संसाधनों को मुक्त करने के लिए कार्यकर्ता को बंद करने के एक विधि प्रदान करें।
ध्यान दें कि यदि कार्यकर्ता एक से अधिक गोरूटीन प्रबंधित करता है, तो एक WaitGroup का उपयोग करना चाहिए।