Channels
Promises/Callbacks vs Channels
หัวข้อที่มีชื่อว่า “Promises/Callbacks vs Channels”ใน JavaScript เมื่อคุณต้องการส่งผลลัพธ์จาก async operation ไปยังโค้ดอื่น คุณใช้ Promises หรือ callbacks:
function fetchUser(id: number): Promise<User> { return new Promise((resolve) => { // ... async work ... resolve(user); });}const user = await fetchUser(1); // รอรับค่าใน Go channels เป็น typed pipe ระดับ first-class สำหรับส่งค่าระหว่าง goroutines channel เป็นทั้งช่องทางสื่อสารและกลไก synchronization ในตัว:
ch := make(chan User) // สร้าง channel ชนิด Usergo func() { ch <- user }() // ส่งค่าเข้า channeluser := <-ch // รับค่าจาก channel (blocking)Unbuffered vs Buffered Channels
หัวข้อที่มีชื่อว่า “Unbuffered vs Buffered Channels”// TypeScript: Promise สำหรับค่าเดียวfunction getResult(): Promise<number> { return new Promise(resolve => { setTimeout(() => resolve(42), 100); });}const result = await getResult();console.log(result); // 42// Go: channel สำหรับส่งค่าระหว่าง goroutinespackage main
import "fmt"
func getResult(ch chan<- int) { ch <- 42 // ส่งค่าเข้า channel}
func main() { ch := make(chan int) // unbuffered channel go getResult(ch) result := <-ch // รับค่า (blocking จนกว่าจะมีค่า) fmt.Println(result) // 42}Buffered Channels
หัวข้อที่มีชื่อว่า “Buffered Channels”Buffered channel มี queue อยู่ภายใน sender จะไม่ block จนกว่า buffer จะเต็ม และ receiver จะไม่ block ตราบใดที่ buffer ยังมีค่าอยู่ ช่วยแยก producer ออกจาก consumer:
// TypeScript: คล้ายกับ buffered queue ด้วย arrayconst queue: number[] = [];function enqueue(val: number) { queue.push(val); // ไม่ block}enqueue(1); enqueue(2); enqueue(3);// ต้อง process ด้วยตัวเอง// Go: buffered channel (queue ขนาด 3)package main
import "fmt"
func main() { ch := make(chan int, 3) // buffer size 3
ch <- 1 // ไม่ block (buffer ยังว่างอยู่) ch <- 2 ch <- 3 // ch <- 4 // จะ block เพราะ buffer เต็ม
fmt.Println(<-ch) // 1 fmt.Println(<-ch) // 2 fmt.Println(<-ch) // 3}Range over Channels
หัวข้อที่มีชื่อว่า “Range over Channels”ใช้ for range ไล่อ่านค่าจาก channel จนกว่าจะถูก close ฝั่ง producer จะ close channel เพื่อบอกว่าส่งครบแล้ว คล้ายกับการ return ออกจาก async generator:
// TypeScript: iterate over async iterableasync function* generate() { yield 1; yield 2; yield 3;}for await (const val of generate()) { console.log(val);}// Go: range over closed channelpackage main
import ( "fmt" "sync")
func produce(ch chan<- int, wg *sync.WaitGroup) { defer wg.Done() for i := 1; i <= 5; i++ { ch <- i }}
func main() { ch := make(chan int, 5) var wg sync.WaitGroup wg.Add(1) go produce(ch, &wg) wg.Wait() close(ch) // ต้อง close ก่อน range
for v := range ch { fmt.Println(v) }}package main
import ( "fmt" "sync")
func producer(ch chan<- int, wg *sync.WaitGroup) { defer wg.Done() for i := 1; i <= 5; i++ { ch <- i }}
func main() { ch := make(chan int, 5) var wg sync.WaitGroup wg.Add(1) go producer(ch, &wg) wg.Wait() close(ch) for v := range ch { fmt.Println("Received:", v) }}Loading Go runtime (first run only, ~8 MB)…