การดู : 0

12/04/2026 18:16น.

JS2GO EP.39 การใช้ Channels และ Pipelines ใน Go สำหรับ Data Processing

JS2GO EP.39 การใช้ Channels และ Pipelines ใน Go สำหรับ Data Processing

#Data Processing

#Concurrency

#Pipelines

#JavaScript

#Go

#Channels

เมื่อคุณต้องจัดการข้อมูลจำนวนมาก เช่น

  • การอ่านไฟล์หลายชุดพร้อมกัน
  • การประมวลผลข้อมูลจาก API หลายแหล่ง
  • หรือการแปลงข้อมูลหลายขั้นตอน (Transform → Filter → Save)

 

สิ่งที่จำเป็นคือเทคนิค Parallel Processing เพื่อเพิ่ม Throughput ของระบบและใช้ทรัพยากรอย่างมีประสิทธิภาพ

 

ทั้ง JavaScript และ Go รองรับการประมวลผลแบบ Asynchronous แต่ใช้แนวทางที่ต่างกันอย่างชัดเจน:

ภาษาแนวทางหลัก
JavaScriptใช้ Promises / async-await / Event Loop
Go (Golang)ใช้ Goroutines + Channels + Pipelines

 

1. แนวคิด Concurrency: JavaScript vs Go

 

คุณสมบัติJavaScriptGo
แนวคิดหลักAsync / Event LoopGoroutines + Channels
แบบจำลองการทำงานSingle-threadedMulti-threaded (lightweight)
การสื่อสารระหว่าง processCallback / EventChannel
จุดแข็งใช้งานง่าย เหมาะกับ I/O-bound tasksประสิทธิภาพสูง เหมาะกับ CPU-bound tasks

 

2. ตัวอย่างพื้นฐาน: Concurrency ใน JavaScript

 

ใน JavaScript การทำงานพร้อมกัน (concurrent execution) สามารถทำได้ด้วย async/await หรือ Promise.all()

 

async function processData() {
  const data = [1, 2, 3, 4, 5];

  const results = await Promise.all(
    data.map(async (n) => {
      await new Promise((r) => setTimeout(r, 500)); // จำลองการประมวลผล
      return n * 2;
    })
  );

  console.log("✅ Processed Data:", results);
}

processData();

 

ผลลัพธ์:
✅ Processed Data: [2, 4, 6, 8, 10]

 

อธิบาย:
JavaScript จะสร้าง Promise สำหรับแต่ละ task แล้วรันพร้อมกันใน background ผ่าน Event Loop

 

3. ตัวอย่างพื้นฐาน: Concurrency ใน Go

 

ใน Go สามารถรันฟังก์ชันพร้อมกันได้ง่ายมากด้วย Goroutines

 

package main

import (
	"fmt"
	"time"
)

func process(n int, ch chan int) {
	time.Sleep(500 * time.Millisecond) // จำลองการประมวลผล
	ch <- n * 2
}

func main() {
	data := []int{1, 2, 3, 4, 5}
	ch := make(chan int)

	for _, n := range data {
		go process(n, ch)
	}

	for i := 0; i < len(data); i++ {
		fmt.Println("✅ Result:", <-ch)
	}
}

 

ผลลัพธ์:

✅ Result: 2
✅ Result: 4
✅ Result: 6
✅ Result: 8
✅ Result: 10

 

อธิบาย:

  • คำสั่ง go process(n, ch) สร้าง goroutine ซึ่งทำงานคู่ขนานกับฟังก์ชันหลัก
  • channel ใช้เป็น “ท่อส่งข้อมูล” ระหว่าง goroutines เพื่อส่งค่ากลับมาอย่างปลอดภัย

 

4. การใช้ Channel

 

Channel คือ “ท่อส่งข้อมูล” ระหว่าง goroutines ซึ่งช่วยให้สื่อสารกันได้โดยไม่ต้องใช้ lock

 

messages := make(chan string)

go func() {
	messages <- "Hello from goroutine"
}()

msg := <-messages
fmt.Println(msg)

 

ผลลัพธ์:
Hello from goroutine

 

สรุป:
✅ Channel ช่วยให้ goroutines ติดต่อกันได้โดยไม่ต้องใช้ mutex หรือ lock
✅ เป็นหัวใจสำคัญของระบบ Concurrent Programming ใน Go

 

5. การออกแบบ Pipeline Pattern ใน Go

 

Pipeline คือการเชื่อมต่อ goroutines หลายตัวเข้าด้วยกันผ่าน channels แต่ละขั้นตอน (stage) จะรับข้อมูลจาก channel หนึ่ง แล้วส่งผลลัพธ์ต่อไปยังอีก channel อย่างต่อเนื่อง

 

🔹 ตัวอย่าง: Simple Pipeline

package main

import "fmt"

// ขั้นตอนที่ 1: สร้างข้อมูล
func generate(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

// ขั้นตอนที่ 2: ประมวลผล (คูณ 2)
func multiply(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * 2
		}
		close(out)
	}()
	return out
}

// ขั้นตอนที่ 3: แสดงผลลัพธ์
func main() {
	nums := generate(1, 2, 3, 4, 5)
	results := multiply(nums)

	for v := range results {
		fmt.Println("✅ Result:", v)
	}
}

 

ผลลัพธ์:
✅ Result: 2
✅ Result: 4
✅ Result: 6
✅ Result: 8
✅ Result: 10

 

อธิบาย:

  • generate() สร้างข้อมูลและส่งผ่าน channel
  • multiply() ประมวลผลแบบ concurrent
  • Channel จะเชื่อมแต่ละขั้นตอนเข้าด้วยกัน ทำให้ทุกส่วนสามารถทำงานพร้อมกันได้

 

6. การทำ Pipeline หลายขั้นตอน

 

คุณสามารถขยาย pipeline ให้ซับซ้อนขึ้นได้ เช่น
generate → square → filter → aggregate → output

 

ตัวอย่าง: Pipeline 3 ขั้นตอน

package main

import "fmt"

func generate(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

func square(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}

func filterEven(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			if n%2 == 0 {
				out <- n
			}
		}
		close(out)
	}()
	return out
}

func main() {
	nums := generate(1, 2, 3, 4, 5)
	squared := square(nums)
	filtered := filterEven(squared)

	for v := range filtered {
		fmt.Println("✅ Filtered Result:", v)
	}
}

 

ผลลัพธ์:
✅ Filtered Result: 4
✅ Filtered Result: 16

 

7. การเปรียบเทียบกับ JavaScript

 

JavaScript ก็สามารถสร้าง pipeline ได้เช่นกัน ด้วย Array methods, async generators, หรือ RxJS

 

async function* generate(nums) {
  for (const n of nums) yield n;
}

async function* square(input) {
  for await (const n of input) yield n * n;
}

async function* filterEven(input) {
  for await (const n of input) if (n % 2 === 0) yield n;
}

for await (const val of filterEven(square(generate([1,2,3,4,5])))) {
  console.log("✅ Filtered Result:", val);
}

 

ข้อดีของ Go:
✅ Concurrency ผ่าน channel มีประสิทธิภาพสูงกว่า
✅ ควบคุม flow และ memory ได้ละเอียด
✅ ไม่มี overhead ของ event loop

 

ข้อดีของ JavaScript:
✅ เขียนง่าย เข้าใจง่าย
✅ เหมาะกับงาน I/O-bound เช่น API requests หรือ streaming

 

8. แนวทางปฏิบัติที่ดี (Best Practices)

 

💡 ใช้ Buffered Channel เช่น make(chan int, 10) เพื่อลดการ block
💡 ปิด channel ทุกครั้งเมื่อ goroutine เสร็จงาน (close(out))
💡 ใช้ select เพื่อ handle timeout หรือ cancellation
💡 สำหรับ pipeline ที่ซับซ้อน ควรแยกแต่ละ stage ออกเป็น function ที่ชัดเจน

 


 

สรุป

 

ประเด็นJavaScriptGo
Async ModelEvent Loop + PromiseGoroutines + Channels
Parallel Executionจำลองผ่าน asyncReal concurrent threads
Pipeline DesignFunctional / StreamChannel-based Pipeline
Performanceดีมากสำหรับ I/O-boundสูงมากสำหรับ CPU-bound
ความซับซ้อนของโค้ดเขียนง่ายกว่าต้องเข้าใจ goroutine และ channel

 

คำแนะนำ:

  • ถ้าเน้น I/O-heavy system (API, streaming, frontend) → ใช้ JavaScript
  • ถ้าเน้น High-performance concurrent processing → ใช้ Go

 

ตอนต่อไป

 

ใน EP.40 ของซีรีส์ JS2GO
เราจะพาคุณไปเรียนรู้ การ Optimize Performance ของโค้ด: Go vs JavaScript
เปรียบเทียบเทคนิคการเพิ่มความเร็ว เช่น Garbage Collection, Memory Profiling, Parallel Execution, และ Benchmark Tools
เพื่อค้นหาว่า “ภาษาไหนเร็วกว่าในโลกจริง” 🧠💨

 

อ่านบทความ Series อื่นๆ

🔵 Facebook: https://www.facebook.com/superdev.academy.th

🔴 YouTube : Superdev Academy

📸 Instagram: Superdev Academy

🎬 TikTok: https://www.tiktok.com/@superdevacademy?lang=th-TH

🌐 Website: https://www.superdevacademy.com/