ข้ามไปยังเนื้อหา

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 ชนิด User
go func() { ch <- user }() // ส่งค่าเข้า channel
user := <-ch // รับค่าจาก channel (blocking)
TypeScript
// TypeScript: Promise สำหรับค่าเดียว
function getResult(): Promise<number> {
return new Promise(resolve => {
setTimeout(() => resolve(42), 100);
});
}
const result = await getResult();
console.log(result); // 42
Go
// Go: channel สำหรับส่งค่าระหว่าง goroutines
package 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 channel มี queue อยู่ภายใน sender จะไม่ block จนกว่า buffer จะเต็ม และ receiver จะไม่ block ตราบใดที่ buffer ยังมีค่าอยู่ ช่วยแยก producer ออกจาก consumer:

TypeScript
// TypeScript: คล้ายกับ buffered queue ด้วย array
const queue: number[] = [];
function enqueue(val: number) {
queue.push(val); // ไม่ block
}
enqueue(1); enqueue(2); enqueue(3);
// ต้อง process ด้วยตัวเอง
Go
// 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
}

ใช้ for range ไล่อ่านค่าจาก channel จนกว่าจะถูก close ฝั่ง producer จะ close channel เพื่อบอกว่าส่งครบแล้ว คล้ายกับการ return ออกจาก async generator:

TypeScript
// TypeScript: iterate over async iterable
async function* generate() {
yield 1; yield 2; yield 3;
}
for await (const val of generate()) {
console.log(val);
}
Go
// Go: range over closed channel
package 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)
}
}
อะไรคือความแตกต่างระหว่าง unbuffered และ buffered channel?
syntax ใดที่ใช้รับค่าจาก channel?
ต้องทำอะไรก่อนใช้ for range บน channel?
chan<- int หมายความว่าอะไร?