สวัสดีครับ ในบทความนี้ก็เป็น EP.6 แล้วนะครับ โดยเนื้อหาจะเป็นเรื่องเกี่ยวกับ Go Channel ซึ่งเป็นเรื่องที่ต่อเนื่องจาก Go EP.5 Go Routine ครับ
สําหรับท่านใดที่ยังไม่ได้อ่าน EP.5 ท่านสามารถกลับไปอ่านก่อนได้นะครับที่นี่ Go EP.5 Go Routine
มาเริ่มเรียนรู้ไปด้วยกันตามหัวข้อด้านล่างเลยครับ
Go Channel คืออะไร
ก่อนอื่นขอทบทวนเนื้อหาใน Go EP.5 Go Routine กันก่อนคือ ในภาษา Go เราสามารถเขียนโปรแกรมแบบ Multi thread ได้โดยใส่ “go” ไว้หน้า Function ที่ต้องการจะให้แยก Thread ออกไปทํางาน แต่ในการใช้งานจริงจะต้องมีการส่งข้อมูลกันระหว่าง Thread หรือหยุดรอผลลัพธ์จาก Function ใดๆก่อนที่จะไปทํา Function ต่อไปด้วย ดังนั้นการที่เราจะส่งข้อมูลกันระหว่าง Thread หรือหยุดรอผลลัพธ์ได้ เราจะใช้สิ่งที่เรียกว่า Go Channel นั่นเอง
เริ่มต้นใช้ Go Channel
ในการใช้งาน Go Channel นั้นเราจะต้องทําการประกาศตัวแปรประเภท Channel ขึ้นมาก่อนดังนี้ครับ
ch := make(chan string)
จาก Code ด้านบนอธิบายได้ดังนี้ครับ สร้างตัวแปรประเภท Channel โดยประเภทของการเก็บข้อมูลเป็น string ซึ่งเราสามารถเก็บข้อมูลเป็นประเภทอื่นๆได้ด้วยเหมือนกันครับเช่น
ch1 := make(chan int)
ch2 := make(chan bool)
จะเห็นว่าในการประกาศตัวแปรประเภท Channel นั้นเราจะใช้ keyword “chan” นําหน้าประเภทของข้อมูลที่เราต้องการจะเก็บ และ make() เข้ามาช่วยในการสร้างตัวแปรขึ้นมา
การที่เราสร้าง Channel ขึ้นมา ให้เรามองว่าเป็นการสร้างท่อขึ้นมารับส่งข้อมูลกันระหว่าง Thread โดยถ้าเราต้องการจะส่งข้อมูลเข้าไปในท่อสามารถทําได้ตามนี้ครับ
ch <- "my data"
จาก Code ด้านบนหมายถึง ส่งข้อมูลเข้าไปในท่อที่ชื่อว่า ch
ต่อมาถ้าเราต้องการจะรับข้อมูลออกมาจากท่อเราสามารถทําได้ดังนี้
a := <-ch
จาก Code ด้านบนหมายถึง รับข้อมูลที่ถูกส่งมาผ่านท่อที่ชื่อว่า ch และในการรับข้อมูลนั้นโปรแกรมจะหยุดรอจนกว่าจะมีการส่งข้อมูลมาผ่านท่อ ch
ถึงตอนนี้เราก็เข้าใจการใช้งาน และการทํางานเบื้องต้นของ Channel กันแล้วนะครับ ต่อมาเราลองนํา Channel มาใช้งานจริงๆกันครับ ตามตัวอย่างนี้
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
ch := make(chan string)
go task1(ch)
task2()
task3()
msgTask1 := <-ch // รอรับข้อมูลจาก Channel ch แล้วเก็บไว้ในตัวแปรชื่อ msgTask1
fmt.Println("Message from task1 : ", msgTask1)
fmt.Println("ใช้เวลาในการ Run ทั้งสิ้น : ", time.Since(start))
}
func task1(ch chan<- string) { // ประกาศ Function โดยรับตัวแปร Channel เข้ามาด้วย
time.Sleep(5 * time.Second)
ch <- "Task1 success" // ส่งข้อมูลผ่านท่อ ch
}
func task2() {
time.Sleep(2 * time.Second)
fmt.Println("Task2 success")
}
func task3() {
time.Sleep(2 * time.Second)
fmt.Println("Task3 success")
}
// ผลลัพธ์จากการ Run
// Task2 success
// Task3 success
// Message from task1 : Task1 success
// ใช้เวลาในการ Run ทั้งสิ้น : 5s
จาก Code ด้านบนอธิบายได้ดังนี้ครับ
ในตัวอย่างเราจะทําให้ task1 แยกออกไปรันในอีก Thread นึง และเมื่อรันเสร็จก็ให้ส่งข้อมูลกลับมา ทําให้เวลาในการทํางานรวมทั้งหมดจากเดิม 9s ลดลงมาเหลือ 5s เท่านั้นเอง
เริ่มจากสร้างตัวแปร Channel ชื่อ ch ขึ้นมาโดยมี Type ของข้อมูลเป็น string และใน Function task1 เราจะรับ ตัวแปรประเภท Channel เข้ามาเพื่อเอามาใช้ในการส่งข้อมูลกลับไปยัง main Thread โดยจะเห็นว่าในการส่งข้อมูลกลับไปยัง Main Thread นั้นเราจะใช้
ch <- "Task1 success" // ส่งข้อมูลผ่านท่อ ch
แล้วใน Main thread เราจะรอรับข้อมูลที่ถูกส่งกลับมาจาก task1 ผ่าน Channel ch โดยเขียนได้แบบนี้
msgTask1 := <-ch // รอรับข้อมูลจาก Channel ch แล้วเก็บไว้ในตัวแปรชื่อ msgTask1
ซึ่งโปรแกรมจะรอที่บรรทัดนี้จนกว่าจะมีการส่งข้อมูลเข้ามาผ่าน Channel ch
มาถึงจุดนี้ เราก็จะสามารถเขียน go แบบ Multi thread ได้แล้ว ซึ่งจําเป็นมากในการเขียนภาษา Go
สําหรับบทความนี้ก็มีเพียงเท่านี้ครับ ขอให้สนุกกับการเขียน Code นะครับ ขอบคุณครับ
สําหรับ EP. ต่อไปจะเป็นเรื่อง Go EP.7 Go Unit Testing เข้าไปอ่านต่อได้เลยครับ