ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်
Part 3 ကတော့ project ရဲ့ နောက်ဆုံးအဆင့်ဖြစ်ပြီး Advanced chapter မှာသင်ခဲ့တဲ့ goroutine, channel concept တွေကို လက်တွေ့ထည့်သုံးပါမယ်။ Program ပိတ်လိုက်တိုင်း task list ပျောက်သွားရင် အသုံးမဝင်တော့တဲ့အတွက် encoding/json package နဲ့ tasks.json file ထဲ save/load လုပ်နည်းသင်ယူပါမယ်။ ဒီအပြင် background goroutine တစ်ခုကို time.Ticker နဲ့ run ထားပြီး periodic auto-save လုပ်တဲ့ pattern ကိုပါ ထည့်သွင်းကြည့်ပါမယ်။ ဒီအဆင့်ပြီးရင် Task Manager project က struct, methods, error handling, file I/O, goroutine ပေါင်းစပ်ထားတဲ့ ပြည့်စုံတဲ့ mini application တစ်ခု ပြီးမြောက်သွားပါလိမ့်မယ်။
လက်တွေ့ ဆောက်ကြည့်မယ်
SaveToFile(filename string) error method ရေးပြီး json.MarshalIndent နဲ့ tasks slice ကို JSON bytes ပြောင်းကာ os.WriteFile သုံးပြီး file ထဲသိမ်းပါ။ LoadFromFile(filename string) error method ရေးပြီး os.ReadFile နဲ့ file ဖတ်ကာ json.Unmarshal နဲ့ tasks slice ထဲ ပြန်ဖြည့်ပါ။ goroutine တစ်ခု start လုပ်ပြီး time.NewTicker(10 * time.Second) သုံးကာ ticker.C channel ကနေ tick ရတိုင်း SaveToFile ကို background မှာ အလိုအလျောက်ခေါ်ပါ။ main() ရဲ့ အဆုံးမှာ program ပိတ်ခါနီးမှ SaveToFile တစ်ကြိမ်ထပ်ခေါ်ပြီး data မပျောက်အောင် အာမခံပါ။
Code နမူနာ
package main
import (
"encoding/json"
"fmt"
"os"
"time"
)
type Task struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
}
type TaskManager struct {
tasks []Task
}
func (m *TaskManager) SaveToFile(filename string) error {
data, err := json.MarshalIndent(m.tasks, "", " ")
if err != nil {
return err
}
return os.WriteFile(filename, data, 0644)
}
func (m *TaskManager) LoadFromFile(filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return err
}
return json.Unmarshal(data, &m.tasks)
}
func (m *TaskManager) startAutoSave(filename string, interval time.Duration, done chan bool) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := m.SaveToFile(filename); err != nil {
fmt.Println("auto-save error:", err)
} else {
fmt.Println("auto-saved to", filename)
}
case <-done:
return
}
}
}
func main() {
manager := &TaskManager{}
_ = manager.LoadFromFile("tasks.json")
manager.tasks = append(manager.tasks, Task{ID: 1, Title: "Finish project"})
done := make(chan bool)
go manager.startAutoSave("tasks.json", 10*time.Second, done)
// program logic runs here...
time.Sleep(2 * time.Second)
done <- true
if err := manager.SaveToFile("tasks.json"); err != nil {
fmt.Println("final save error:", err)
}
fmt.Println("Task Manager project complete!")
}tasks.json file ထဲမှာ task list ကို formatted JSON အနေနဲ့ save ဖြစ်သွားပြီး program ပိတ်တဲ့အခါမှာလည်း data မပျောက်ပါ။၅ မိနစ် စမ်းကြည့်
5 minutes အတွင်း auto-save interval ကို 10 seconds ကနေ 2 seconds ပြောင်းကြည့်ပြီး tasks.json file ကို editor နဲ့ ဖွင့်ကာ content ဘယ်လို update ဖြစ်သွားလဲ observe လုပ်ကြည့်ပါ။
သတိလေးတစ်ချက်
Production app တစ်ခုမှာ file write လုပ်နေတုန်း program crash ဖြစ်ရင် data corrupt ဖြစ်နိုင်လို့ temp file ရေးပြီးမှ os.Rename နဲ့ atomic ပြောင်းတဲ့ pattern ကို ပိုကောင်းအောင် အသုံးပြုနိုင်ပါတယ်။