ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်
Part 1 မှာ function-based approach သုံးခဲ့ပေမယ့် Part 2 မှာတော့ Methods chapter မှာသင်ခဲ့တဲ့ receiver method pattern ကို သုံးပြီး code ပိုတည်ငြိမ်အောင် refactor လုပ်ပါမယ်။ tasks slice ကို TaskManager struct တစ်ခုရဲ့ field အဖြစ်ထည့်ပြီး Add, List, Complete, Remove တွေကို ဒီ struct ပေါ်က method အဖြစ် ပြန်ရေးပါမယ်။ Complete နဲ့ Remove ကတော့ ID မှားနေရင် ဘာဖြစ်လဲဆိုတာ ကိုင်တွယ်ရမှာမို့ Errors chapter မှာသင်ခဲ့တဲ့ error return pattern ကို လက်တွေ့ အသုံးချရပါမယ်။ ဒီအဆင့်ပြီးရင် project က struct + methods + error handling ပေါင်းစပ်ထားတဲ့ ပိုမှန်ကန်တဲ့ Go design ပုံစံဖြစ်လာပါလိမ့်မယ်။
လက်တွေ့ ဆောက်ကြည့်မယ်
TaskManager struct ကို tasks []Task field တစ်ခုတည်းနဲ့ define လုပ်ပါ။ pointer receiver (m *TaskManager) သုံးပြီး Add(title string), List(), Complete(id int) error, Remove(id int) error method လေးခုရေးပါ။ Complete နဲ့ Remove method နှစ်ခုစလုံးမှာ for loop နဲ့ ID ကို ရှာပြီး ID မတွေ့ရင် fmt.Errorf("task %d not found", id) ကို return ပြန်ပါ။ Remove မှာ slices trick (append(tasks[:i], tasks[i+1:]...)) သုံးပြီး task ကို list ထဲကနေ ဖယ်ပါ။ main() ထဲမှာ Complete/Remove ခေါ်ပြီး error ကို if err != nil နဲ့ check ပြီး print ထုတ်ပါ။
Code နမူနာ
package main
import "fmt"
type Task struct {
ID int
Title string
Done bool
}
type TaskManager struct {
tasks []Task
}
func (m *TaskManager) Add(title string) {
t := Task{ID: len(m.tasks) + 1, Title: title}
m.tasks = append(m.tasks, t)
}
func (m *TaskManager) List() {
for _, t := range m.tasks {
status := "[ ]"
if t.Done {
status = "[x]"
}
fmt.Printf("%s %d. %s\n", status, t.ID, t.Title)
}
}
func (m *TaskManager) Complete(id int) error {
for i := range m.tasks {
if m.tasks[i].ID == id {
m.tasks[i].Done = true
return nil
}
}
return fmt.Errorf("task %d not found", id)
}
func (m *TaskManager) Remove(id int) error {
for i, t := range m.tasks {
if t.ID == id {
m.tasks = append(m.tasks[:i], m.tasks[i+1:]...)
return nil
}
}
return fmt.Errorf("task %d not found", id)
}
func main() {
manager := &TaskManager{}
manager.Add("Learn Go basics")
manager.Add("Build task manager")
if err := manager.Complete(1); err != nil {
fmt.Println("Error:", err)
}
if err := manager.Remove(5); err != nil {
fmt.Println("Error:", err)
}
manager.List()
}Task 1 ကို complete လုပ်ပြီးတဲ့အပြင် ID 5 ကို remove လုပ်ဖို့ကြိုးစားရာမှာ "Error: task 5 not found" ဆိုပြီး print ထုတ်ပေးပါလိမ့်မယ်။၅ မိနစ် စမ်းကြည့်
5 minutes အတွင်း Update(id int, newTitle string) error ဆိုတဲ့ method အသစ်တစ်ခု ထပ်ထည့်ပြီး task title ကို ID နဲ့ ရှာပြောင်းနိုင်အောင် ကိုယ်တိုင် implement လုပ်ကြည့်ပါ။
သတိလေးတစ်ချက်
Remove method ထဲက append(m.tasks[:i], m.tasks[i+1:]...) က slice underlying array ကို share သုံးတာဖြစ်လို့ concurrent access ရှိရင် data race ဖြစ်နိုင်တာကို သတိထားပါ။