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); // await the Promiseใน Go channels เป็น typed pipe ระดับ first-class สำหรับส่งค่าระหว่าง goroutines channel เป็นทั้งช่องทางสื่อสารและกลไก synchronization ในตัว:
ch := make(chan User) // create a channel for User valuesgo func() { ch <- user }() // send into the channeluser := <-ch // receive from the channel (blocks until a value arrives)Unbuffered vs Buffered Channels
หัวข้อที่มีชื่อว่า “Unbuffered vs Buffered Channels”// TypeScript: Promise for a single future valuefunction getResult(): Promise<number> { return new Promise(resolve => { setTimeout(() => resolve(42), 100); });}const result = await getResult();console.log(result); // 42// Go: unbuffered channel — sender and receiver sync uppackage main
import "fmt"
func getResult(ch chan<- int) { ch <- 42 // send; blocks until someone receives}
func main() { ch := make(chan int) // unbuffered go getResult(ch) result := <-ch // receive; blocks until sender sends fmt.Println(result) // 42}Buffered Channels
หัวข้อที่มีชื่อว่า “Buffered Channels”Buffered channel มี queue อยู่ภายใน sender จะไม่ block จนกว่า buffer จะเต็ม และ receiver จะไม่ block ตราบใดที่ buffer ยังมีค่าอยู่ ช่วยแยก producer ออกจาก consumer:
// TypeScript: simulate a buffer with an arrayconst queue: number[] = [];function enqueue(val: number) { queue.push(val); // does not block}enqueue(1); enqueue(2); enqueue(3);// must drain it yourself// Go: buffered channel with a queue of 3package main
import "fmt"
func main() { ch := make(chan int, 3) // buffer capacity 3
ch <- 1 // does not block (space available) ch <- 2 ch <- 3 // ch <- 4 // would block — buffer full
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: async generator as an iterable streamasync function* generate() { yield 1; yield 2; yield 3;}for await (const val of generate()) { console.log(val);}// Go: range over a channel closed by the producerpackage 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) // signal: no more values
for v := range ch { // drains until channel is closed 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) }}Compiling on go.dev (Go 1.27)… offline? an in-browser runtime (~8 MB, Go 1.26) is used instead