Goroutines
Async Functions vs Goroutines
หัวข้อที่มีชื่อว่า “Async Functions vs Goroutines”ใน TypeScript คุณมาร์ค function เป็น async แล้ว await ผลลัพธ์ ทุกครั้งที่เจอ await function จะหยุดพักและคืน control ให้ event loop แต่ทุกอย่างยังรันบน thread เดียว:
async function processUser(id: number) { const user = await fetchUser(id); return user;}// ต้อง await หรือ .then() เพื่อรอผลawait processUser(1);ใน Go คุณเติม keyword go หน้า function call ใดก็ได้ call นั้นจะถูก dispatch เป็น goroutine — หน่วยทำงานน้ำหนักเบาที่รันอิสระ จัดการโดย Go runtime ไม่ต้องมี async ที่ตัว function และไม่ต้อง await ตอนเรียก:
go processUser(1) // รันในพื้นหลังทันที — ไม่ต้อง async keywordจุดต่างที่สำคัญ: async function ของ JavaScript ยังรันบน thread เดียว แต่ goroutine รันแบบ parallel บน OS thread คนละตัวได้จริง
การสร้าง Goroutines
หัวข้อที่มีชื่อว่า “การสร้าง Goroutines”// TypeScript: async/await (single-threaded)async function greet(name: string): Promise<void> { console.log(`Hello from ${name}`);}
// ต้อง await เพื่อรอผลawait greet("Alice");await greet("Bob"); // รันตามลำดับ
// Promise.all เพื่อรันพร้อมกัน (แต่ยังคง single-threaded)await Promise.all([greet("Alice"), greet("Bob")]);// Go: goroutines (truly concurrent)package main
import ( "fmt" "sync")
func greet(name string, wg *sync.WaitGroup) { defer wg.Done() // แจ้ง WaitGroup เมื่อเสร็จ fmt.Printf("Hello from %s\n", name)}
func main() { var wg sync.WaitGroup names := []string{"Alice", "Bob", "Carol"}
for _, name := range names { wg.Add(1) // ลงทะเบียนก่อน launch go greet(name, &wg) // launch goroutine }
wg.Wait() // block จนกว่าทุก goroutine เสร็จ fmt.Println("All done!")}sync.WaitGroup — รอ Goroutines ให้เสร็จ
หัวข้อที่มีชื่อว่า “sync.WaitGroup — รอ Goroutines ให้เสร็จ”sync.WaitGroup เป็นเครื่องมือหลักของ Go สำหรับรอ goroutines กลุ่มหนึ่งให้เสร็จ ทำงานคล้าย Promise.all แต่ใช้ counter แทน array:
wg.Add(n)— เพิ่ม counter ก่อน launch goroutinewg.Done()— ลด counter เมื่อ goroutine เสร็จ (เกือบทุกครั้งใช้คู่กับdefer)wg.Wait()— block จนกว่า counter จะเป็น 0
กฎ: เรียก
wg.Add(1)ก่อนgo f()เสมอ อย่าเรียกข้างใน goroutine เพราะ scheduler อาจไปถึงwg.Wait()ก่อนที่ goroutine จะเริ่มรันด้วยซ้ำ ทำให้Waitคืนค่าทันทีทั้งที่งานยังค้างอยู่
Anonymous Goroutines
หัวข้อที่มีชื่อว่า “Anonymous Goroutines”เหมือน immediately-invoked arrow function ใน JS คุณ launch goroutine แบบ anonymous inline ได้เลย:
// TypeScript: immediately invoked async(async () => { const result = await doSomething(); console.log(result);})();// Go: immediately launched goroutinego func() { result := doSomething() fmt.Println(result)}() // วงเล็บ () ด้านหลังเพื่อ invoke ทันทีpackage main
import ( "fmt" "sync")
func printSquare(n int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("%d² = %d\n", n, n*n)}
func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go printSquare(i, &wg) } wg.Wait() fmt.Println("All squares printed")}Loading Go runtime (first run only, ~8 MB)…