আমার কাছে একটি গোরোটিন রয়েছে যা একটি পদ্ধতি কল করে এবং একটি চ্যানেলে প্রত্যাবর্তিত মানটি দেয়:
ch := make(chan int, 100)
go func(){
for {
ch <- do_stuff()
}
}()
আমি কীভাবে এমন গোরোটিন বন্ধ করব?
আমার কাছে একটি গোরোটিন রয়েছে যা একটি পদ্ধতি কল করে এবং একটি চ্যানেলে প্রত্যাবর্তিত মানটি দেয়:
ch := make(chan int, 100)
go func(){
for {
ch <- do_stuff()
}
}()
আমি কীভাবে এমন গোরোটিন বন্ধ করব?
উত্তর:
সম্পাদনা: আমি এই উত্তরটি তড়িঘড়ি করে লিখেছিলাম, বুঝতে পারার আগে যে আপনার প্রশ্নটি গোরোটিনের অভ্যন্তরে কোনও চ্যানে মান পাঠানো। উপরে প্রস্তাবিত হিসাবে অতিরিক্ত চ্যানের সাহায্যে নীচের পদ্ধতিটি ব্যবহার করা যেতে পারে, বা আপনার ইতিমধ্যে যে চ্যানটি দ্বি-দিকনির্দেশক তা ব্যবহার করে আপনি কেবলমাত্র একটিটি ব্যবহার করতে পারেন ...
যদি আপনার গুরোটাইন কেবল চ্যান থেকে বেরিয়ে আসা আইটেমগুলি প্রক্রিয়া করার জন্য বিদ্যমান থাকে তবে আপনি "বন্ধ" বিল্টিন এবং চ্যানেলগুলির জন্য বিশেষ প্রাপ্ত ফর্মটি ব্যবহার করতে পারেন।
এটি হ'ল একবার চ্যানে আইটেম পাঠানো শেষ হয়ে গেলে আপনি এটি বন্ধ করে দিন। তারপরে আপনার গোরোটিনের অভ্যন্তরে আপনি রিসিভ অপারেটরের একটি অতিরিক্ত প্যারামিটার পাবেন যা চ্যানেলটি বন্ধ হয়েছে কিনা তা দেখায়।
এখানে একটি সম্পূর্ণ উদাহরণ রয়েছে (গুরোটিন সম্পূর্ণ না হওয়া পর্যন্ত প্রক্রিয়াটি অব্যাহত থাকে তা নিশ্চিত করার জন্য ওয়েটগ্রুপ ব্যবহার করা হয়):
package main
import "sync"
func main() {
var wg sync.WaitGroup
wg.Add(1)
ch := make(chan int)
go func() {
for {
foo, ok := <- ch
if !ok {
println("done")
wg.Done()
return
}
println(foo)
}
}()
ch <- 1
ch <- 2
ch <- 3
close(ch)
wg.Wait()
}
defer
হয় wg.Done()
এবং range ch
চ্যানেলটি বন্ধ না হওয়া পর্যন্ত সমস্ত মানকে পুনরুক্ত করে lo
সাধারণত, আপনি জোরোটাইন একটি (সম্ভবত পৃথক) সংকেত চ্যানেলটি পাস করেন। আপনি যখন গোরোটিন থামাতে চান সেই সংকেত চ্যানেলটি কোনও মানকে ঠেলে দিতে ব্যবহৃত হয়। নিয়মিতভাবে চ্যানেলটি জোরোটাইন পোল করে। এটি একটি সংকেত সনাক্ত করার সাথে সাথে এটি প্রস্থান করে।
quit := make(chan bool)
go func() {
for {
select {
case <- quit:
return
default:
// Do other stuff
}
}
}()
// Do stuff
// Quit goroutine
quit <- true
আপনি বাইরে থেকে গোরোটিন মারতে পারবেন না। আপনি কোনও চ্যানেল ব্যবহার বন্ধ করতে গোরোটিনকে সিগন্যাল করতে পারেন, তবে কোনও ধরণের মেটা পরিচালনা করার জন্য গোরোটিনগুলিতে কোনও হ্যান্ডেল নেই। গোরআটাইনগুলি সহযোগিতামূলকভাবে সমস্যাগুলি সমাধান করার উদ্দেশ্যে করা হয়েছে, সুতরাং দুর্ব্যবহারকারীকে হত্যা করা প্রায়শই পর্যাপ্ত প্রতিক্রিয়া হতে পারে না। আপনি যদি দৃ rob়তার জন্য বিচ্ছিন্নতা চান তবে আপনি সম্ভবত একটি প্রক্রিয়া চান।
সাধারণত, আপনি একটি চ্যানেল তৈরি করতে এবং গোরোটিনে স্টপ সিগন্যাল পেতে পারেন।
এই উদাহরণে চ্যানেল তৈরির দুটি উপায়।
চ্যানেল
প্রসঙ্গ । উদাহরণে আমি ডেমো করব willcontext.WithCancel
প্রথম ডেমো, ব্যবহার করুন channel
:
package main
import "fmt"
import "time"
func do_stuff() int {
return 1
}
func main() {
ch := make(chan int, 100)
done := make(chan struct{})
go func() {
for {
select {
case ch <- do_stuff():
case <-done:
close(ch)
return
}
time.Sleep(100 * time.Millisecond)
}
}()
go func() {
time.Sleep(3 * time.Second)
done <- struct{}{}
}()
for i := range ch {
fmt.Println("receive value: ", i)
}
fmt.Println("finish")
}
দ্বিতীয় ডেমো, ব্যবহার করুন context
:
package main
import (
"context"
"fmt"
"time"
)
func main() {
forever := make(chan struct{})
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
for {
select {
case <-ctx.Done(): // if cancel() execute
forever <- struct{}{}
return
default:
fmt.Println("for loop")
}
time.Sleep(500 * time.Millisecond)
}
}(ctx)
go func() {
time.Sleep(3 * time.Second)
cancel()
}()
<-forever
fmt.Println("finish")
}
আমি জানি এই উত্তরটি ইতিমধ্যে গ্রহণ করা হয়েছে, তবে আমি ভেবেছিলাম আমার 2 টি ছোঁড়া ভিতরে ফেলে দেব I আমি সমাধি প্যাকেজটি ব্যবহার করতে পছন্দ করি । এটি মূলত একটি উত্সাহিত ছাড়ার চ্যানেল, তবে এটি কোনও ত্রুটিও ফিরে দেওয়ার মতো দুর্দান্ত কাজ করে। নিয়ন্ত্রণাধীন রুটিনটিতে এখনও রিমোট কিল সিগন্যালগুলির জন্য চেক করার দায়িত্ব রয়েছে। আফাইক কোনও গোরোটিনের "আইডি" পাওয়া এবং এটি খারাপ ব্যবহার করে (যেমন: অসীম লুপে আটকে) থাকলে এটি হত্যা করা সম্ভব নয়।
এখানে আমি একটি সাধারণ উদাহরণ যা পরীক্ষা করেছি:
package main
import (
"launchpad.net/tomb"
"time"
"fmt"
)
type Proc struct {
Tomb tomb.Tomb
}
func (proc *Proc) Exec() {
defer proc.Tomb.Done() // Must call only once
for {
select {
case <-proc.Tomb.Dying():
return
default:
time.Sleep(300 * time.Millisecond)
fmt.Println("Loop the loop")
}
}
}
func main() {
proc := &Proc{}
go proc.Exec()
time.Sleep(1 * time.Second)
proc.Tomb.Kill(fmt.Errorf("Death from above"))
err := proc.Tomb.Wait() // Will return the error that killed the proc
fmt.Println(err)
}
ফলাফলটি দেখতে হবে:
# Loop the loop
# Loop the loop
# Loop the loop
# Loop the loop
# Death from above
tomb
উদাহরণস্বরূপ, আতঙ্ক ছুঁড়ে এমন কিছু ঘটলে যদি গোরোটিনের সাথে কী ঘটে তা আপনি পরীক্ষা করে দেখেছেন ? টেকনিক্যালি এই ক্ষেত্রে হবে ভাষী, goroutine প্রস্থানের, তাই আমি অভিমানী করছি এটি এখনও পিছিয়ে কল proc.Tomb.Done()
...
proc.Tomb.Done()
প্যানিকটি প্রোগ্রামটি ক্র্যাশ হওয়ার আগেই সম্পাদন করবে, তবে কি শেষ? এটি সম্ভব যে মূল গোরোটিনের কাছে কিছু বিবৃতি কার্যকর করার খুব সামান্য একটি উইন্ডো থাকতে পারে , তবে এটি অন্য গোরোটিনে আতঙ্ক থেকে পুনরুদ্ধারের কোনও উপায় নেই, সুতরাং প্রোগ্রামটি এখনও ক্র্যাশ করে। ডকস বলেছেন: "ফাংশন এফ আতঙ্কের ডাক দেয়, এফের এক্সিকিউশন বন্ধ হয়ে যায়, এফের যে কোনও স্থগিত ফাংশন স্বাভাবিকভাবে কার্যকর করা হয় এবং তারপরে এফ তার কলারে ফিরে আসে the বর্তমান গরোটিনের সমস্ত ফাংশন ফিরে না আসা পর্যন্ত প্রক্রিয়াটি স্ট্যাক অব্যাহত রাখে, যে মুহুর্তে প্রোগ্রামটি ক্র্যাশ হয়ে গেছে ""
ব্যক্তিগতভাবে, আমি গুরোটিনের একটি চ্যানেলে রেঞ্জটি ব্যবহার করতে চাই:
https://play.golang.org/p/qt48vvDu8cd
ডেভ এই সম্পর্কে একটি দুর্দান্ত পোস্ট লিখেছেন: http://dave.cheney.net/2013/04/30/curious-channels ।