Timeouts
#
// *Timeout* တွေဟာ ပြင်ပ resource တွေနဲ့ ချိတ်ဆက်တဲ့ ပရိုဂရမ်တွေ သို့မဟုတ်
// အလုပ်လုပ်ချိန်ကို ကန့်သတ်ဖို့လိုအပ်တဲ့ ပရိုဂရမ်တွေအတွက် အရေးကြီးပါတယ်။
// Go မှာ timeout တွေကို implement လုပ်ဖို့ channel တွေနဲ့ `select` ကြောင့်
// လွယ်ကူပြီး သပ်ရပ်ပါတယ်။
package main
import (
"fmt"
"time"
)
func main() {
// ဥပမာအနေနဲ့၊ ပြင်ပ function call တစ်ခုက သူ့ရဲ့ရလဒ်ကို 2 စက္ကန့်ကြာပြီးမှ
// `c1` ဆိုတဲ့ channel ပေါ်မှာ ပြန်ပေးတယ်ဆိုပါစို့။ သတိပြုရမှာက ဒီ channel က
// buffered ဖြစ်ပါတယ်၊ ဒါကြောင့် goroutine ထဲက send လုပ်တာက nonblocking ဖြစ်ပါတယ်။
// ဒါဟာ channel ကို ဘယ်တော့မှ မဖတ်ဖြစ်တဲ့အခါ goroutine leak တွေကို
// ကာကွယ်ဖို့ အသုံးများတဲ့ pattern တစ်ခုဖြစ်ပါတယ်။
c1 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c1 <- "result 1"
}()
// ဒီမှာတော့ timeout ကို implement လုပ်တဲ့ `select` ပါ။
// `res := <-c1` က ရလဒ်ကို စောင့်ပါတယ်၊ `<-time.After` ကတော့
// 1 စက္ကန့် timeout ကြာပြီးမှ ပို့မယ့်တန်ဖိုးကို စောင့်ပါတယ်။
// `select` က ပထမဆုံး အဆင်သင့်ဖြစ်တဲ့ receive ကို ရွေးချယ်တဲ့အတွက်
// operation က ခွင့်ပြုထားတဲ့ 1 စက္ကန့်ထက် ပိုကြာရင် timeout case ကို ယူမှာဖြစ်ပါတယ်။
select {
case res := <-c1:
fmt.Println(res)
case <-time.After(1 * time.Second):
fmt.Println("timeout 1")
}
// 3 စက္ကန့်ဆိုတဲ့ ပိုကြာတဲ့ timeout ကို ခွင့်ပြုရင်တော့
// `c2` ကနေ လက်ခံတာ အောင်မြင်ပြီး ရလဒ်ကို print ထုတ်ပါလိမ့်မယ်။
c2 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c2 <- "result 2"
}()
select {
case res := <-c2:
fmt.Println(res)
case <-time.After(3 * time.Second):
fmt.Println("timeout 2")
}
}
# ဒီပရိုဂရမ်ကို run လိုက်တဲ့အခါ ပထမ operation
# က timeout ဖြစ်သွားပြီး
# ဒုတိယ operation success ဖြစ်တာ တွေ့ရပါတယ်။
$ go run timeouts.go
timeout 1
result 2