ไปฟังเรื่อง Goroutine, Channel และ Parallelism จากงาน Go Get # 2 จากกลุ่ม Golang Thailand
ก็เลยกลับมานั่งสรุปกันนิดหน่อย
เพราะว่าเป็นเรื่องที่มีโอกาสใช้งานน้อยมาก ๆ
ตั้งแต่ทำ project ด้วยภาษา Go มาเคยใช้เพียง project เดียวเอง
เลยกลับมาสรุปเพื่อทำความเข้าใจกันหน่อย

โดยเริ่มจากเรื่องง่าย ๆ ก่อนคือ Goroutine และ Channel
ซึ่งเป็นเรื่องพื้นฐานสุด ๆ แต่ก็ไม่ง่ายเลยนะ
มาเริ่มกันเลย

ในการศึกษาภาษา Go นั้น ช่วงแรก ๆ จะเจอรูปแบบภาษาง่าย ๆ เข้าใจง่าย

บางครั้งมันอาจจะดูเยอะ ทำไมต้องทำขนาดนี้ด้วย
แต่ตัวภาษามันก็ตรงไปตรงมา จะทไอะไรก็เขียนบอกไป
พอมาถึงเรื่อง Goroutine และ Channel เท่านั้นแหละ บอกเลยว่า งงมาก ๆ
เนื่องจากเป็นแนวคิดที่เราไม่คุ้นชินมากนัก
ดังนั้นจึงต้องใช้เวลาในการศึกษาและทำความเข้าใจกันหน่อย
แต่ผมคิดว่า ถ้าเราเข้าใจแล้ว มันจะคุ้มค่ามาก ๆ
เพราะว่า ทำให้เราได้วิธีการแก้ไขปัญหาเพิ่มขึ้นมาอีกทางแล้ว

เริ่มจาก Goroutine

ทำการ run ดังนี้

คำอธิบาย
สังเกตุว่าจะมี keyword ว่า go
สำหรับการ run Go routine ขึ้นมาอีก 1 ตัว
ทำให้มีการทำงาน 2 ส่วนแยกกันดังรูป

โดยที่จาก code นั้น main() ไม่สามารถเข้าถึงผลการทำงานจาก hello() ได้เลย
และทำการ hack ในส่วนของ main นิดหน่อย เพื่อให้รอการทำงานของ hello()
ด้วยการให้ main() รอด้วยการ sleep
เพราะว่าทั้งสองส่วนทำงานแยกกันอย่างชัดเจน

แต่ถ้าเราต้องการผลการทำงานจาก Hello() ละ จะทำอย่างไร ?

สิ่งที่ต้องทำคือ การเพิ่ม channel ระหว่างทั้งคู่เข้าไป
โดยสิ่งแรกที่ต้องการคือ รับผลการทำงานจาก Hello() กลับมาดังรูป

เขียน code ได้ดังนี้

ทำการ run ดังนี้

คำอธิบาย
ทำการสร้าง channel ชื่อว่า result โดยชนิดข้อมูลที่ส่งใน channel คือ string
จากนั้นทำการส่งไปยัง hello()
ใน hello() จะพบว่า ผลลัพธ์ของการทำงานจะถูกส่งเข้าไปยัง channel ที่ส่งมา
สุดท้ายใน main() จะรอผลการทำงานจาก channel ด้วย <-result
ทำให้ไม่ต้องใช้ sleep() รออีกต่อไป

ดังนั้นถ้าจะเขียนรูปให้ถูกมากยิ่งขึ้นจะเป็นดังรูป
ซึ่งเป็นการทำงานแบบ unidirection หรือ ทางเดียวเท่านั้น

แต่ถ้าเราต้องการให้ main() และ hello() คุยกันแบบสองทาง หรือ Bidirection ละ ทำอย่างไร ?

โดยตรงนี้จะยิ่งเพิ่มความมึนงงมากยิ่งขึ้น
นั่นคือจะสร้าง 2 channel ขึ้นมา

  1. Channel ที่ 1 ทำการส่ง input จาก main() ไปยัง hello()
  2. Channel ที่ 2 ทำการส่งผลการทำงานจาก hello() ไปยัง main()

แสดงดังรูป

สังเกตุว่าใน function hello() นั้นจะมี channel สองตัวที่ต่างกัน

  • <-chan string คือ input ที่ส่งเข้ามาใน channel ซึ่งตัวอย่างส่งมาจาก main()
  • chan<- string คือ output ที่จะส่งผลการทำงานจาก hello() ออกไป ซึ่งจากตัวอย่างนี้ main() ก็จะรอรับข้อมูลนี้อยู่

น่าจะทำให้เข้าใจเรื่องของ Go routine มากยิ่งขึ้น
ซึ่งยังมีเรื่อง multi-channel อีก ซึ่งมันคือเรื่องของ concurrent ที่ไว้อธิบายต่อไป
แต่สิ่งที่น่าสนใจคือ ก่อนการจะเขียน code นั้น
จำเป็นต้องวาดภาพอธิบายสิ่งที่ต้องการก่อนนะ
ขอให้สนุกกับการเขียน code ครับ

Reference Websites
https://gobyexample.com/goroutines
https://www.sohamkamani.com/blog/2017/08/24/golang-channels-explained/
https://abronan.com/introduction-to-goroutines-and-go-channels/
https://notes.shichao.io/gopl/ch8/
https://medium.com/@tilaklodha/concurrency-and-parallelism-in-golang-5333e9a4ba64
https://stackoverflow.com/questions/39826692/what-are-golang-channels-used-for/39831976
https://medium.com/@trevor4e/learning-gos-concurrency-through-illustrations-8c4aff603b3