Context
#
// ယခင်ဥပမာမှာ ရိုးရှင်းတဲ့ HTTP server တစ်ခုတည်ဆောက်တာကို ကြည့်ခဲ့ပြီးပါပြီ။
// HTTP server တွေဟာ context.Context ကိုသုံးပြီး cancel လုပ်တာကို
// သရုပ်ပြဖို့ အသုံးဝင်ပါတယ်။ Context က deadline တွေ၊ cancel signal တွေနဲ့
// တခြား request-scoped value တွေကို API boundary တွေနဲ့ goroutine တွေကြား
// သယ်ဆောင်ပေးပါတယ်။
package main
import (
"fmt"
"net/http"
"time"
)
func hello(w http.ResponseWriter, req *http.Request) {
// `context.Context` တစ်ခုကို `net/http` စက်ယန္တရား(machinery)က request တိုင်းအတွက်
// ဖန်တီးပေးပြီး `Context()` method နဲ့ ရယူနိုင်ပါတယ်။
ctx := req.Context()
fmt.Println("server: hello handler started")
defer fmt.Println("server: hello handler ended")
// Client ဆီ ပြန်စာမပို့ခင် စက္ကန့်အနည်းငယ် စောင့်ပါမယ်။ ဒါဟာ server က
// အလုပ်လုပ်နေတာကို simulate လုပ်တာလို့ ယူဆနိုင်ပါတယ်။ အလုပ်လုပ်နေစဉ်မှာ
// context ရဲ့ `Done()` channel ကို စောင့်ကြည့်နေပြီး အလုပ်ကို cancel လုပ်ပြီး
// အမြန်ဆုံး ပြန်သွားဖို့ signal ကို စောင့်ကြည့်နေပါတယ်။
select {
case <-time.After(10 * time.Second):
fmt.Fprintf(w, "hello\n")
case <-ctx.Done():
// context ရဲ့ `Err()` method က `Done()` channel
// ဘာကြောင့် ပိတ်သွားတယ်ဆိုတာကို
// ရှင်းပြတဲ့ error တစ်ခုကို ပြန်ပေးပါတယ်။
err := ctx.Err()
fmt.Println("server:", err)
internalError := http.StatusInternalServerError
http.Error(w, err.Error(), internalError)
}
}
func main() {
// အရင်ကလိုပဲ handler ကို "/hello" route မှာ register လုပ်ပြီး
// server စတင်လည်ပတ်စေပါတယ်။
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8090", nil)
}
# Server ကို နောက်ခံမှာ run ပါ။
$ go run context-in-http-servers.go &
# Client က `/hello` ကို request
# လုပ်တာကို simulate လုပ်ပါ။
# စလိုက်ပြီး မကြာခင်မှာပဲ Ctrl+C နှိပ်ပြီး
# cancel လုပ်တာကို signal ပေးပါ။
$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended