เมื่อพูดถึงการพัฒนาซอฟต์แวร์หรือโปรแกรมที่สามารถทำงานได้หลายกระบวนการพร้อมกัน (concurrency),ภาษาโปรแกรม Go นับว่าเป็นหนึ่งในภาษาโปรแกรมที่มีความโดดเด่นในด้านนี้ โดยเฉพาะการจัดการ concurrency ผ่าน Goroutine ซึ่งเป็นหนึ่งในคุณสมบัติที่ทำให้ Go ได้รับความนิยมในวงกว้าง วันนี้เราจะพาคุณมาทำความรู้จักกับ Goroutine และเหตุผลว่าทำไมคุณควรใช้ Goroutine ในการพัฒนาโปรแกรม
Goroutine คือการทำงานคู่ขนานแบบ lightweight ที่มีการจัดการโดย Go runtime เหมือนกับ thread ในภาษาอื่น ๆ แต่ต่างกันที่ Goroutine ใช้ทรัพยากรที่น้อยกว่า ซึ่งทำให้เราสามารถรัน Goroutine ได้เป็นจำนวนมากในโปรแกรมเดียว โดยไม่ต้องกังวลเรื่องหน่วยความจำหรือการแย่งชิงทรัพยากรระหว่าง Goroutine
การเริ่มต้น Goroutine นั้นง่ายมาก เพียงใช้คำสั่ง `go` หน้าฟังก์ชันที่ต้องการให้ทำงานแบบ concurrent โค้ดตัวอย่างดังนี้:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world") // run as a Goroutine
say("hello")
}
ในตัวอย่างนี้ ฟังก์ชัน `say` ถูกเรียกใช้งานในฐานะ Goroutine โดยผ่านคำสั่ง `go say("world")` ส่งผลให้มีการดำเนินการของฟังก์ชัน `say` พร้อมกันสองครั้ง คือ "hello" และ "world" อย่างไม่มีลำดับตายตัว
แม้ว่า Goroutine จะถูกเปรียบเทียบกับ thread อยู่บ่อยครั้ง แต่ทั้งสองมีความแตกต่างกันในหลายแง่มุม เช่น:
1. ทรัพยากรที่ใช้: Goroutine เริ่มต้นด้วยขนาด stack เพียงประมาณ 2KB ในขณะที่ thread ทั่วไปมักใช้ stack ขนาดใหญ่กว่า 2. การจัดการ: Go runtime ให้การจัดการ scheduling ของ Goroutine อย่างมีประสิทธิภาพ ทำให้พัฒนาซอฟต์แวร์เป็นไปได้อย่างราบรื่น
ลองจินตนาการถึงแอปพลิเคชันเซิร์ฟเวอร์ที่รองรับการร้องขอ HTTP หลายพันตัวในเวลาเดียวกัน ด้วย Goroutine เราสามารถจัดการคำร้องขอเหล่านี้ได้พร้อมกัน โดยที่แต่ละ Goroutine สามารถรับและตอบสนองได้อย่างรวดเร็วและแยกเป็นอิสระ:
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
ในโค้ดนี้ ฟังก์ชัน `handler` จะถูกรวมใช้ใน Goroutine แยกต่างหากเมื่อมีคำร้องขอ HTTP เข้ามา
แม้ว่า Goroutine จะมีข้อดี แต่อาจต้องระวังเรื่องการสื่อสารระหว่าง Goroutine และการจัดการข้อมูลร่วมกันเพื่อป้องกัน race conditions สามารถแก้ไขปัญหานี้โดยใช้ channel ซึ่งเป็นเครื่องมือสำคัญในการสื่อสารระหว่าง Goroutine ใน Go
ตัวอย่างการใช้ channel:
package main
import (
"fmt"
"time"
)
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // ส่งผลรวมไปยัง channel
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c) // ส่งครึ่งแรกของ slice
go sum(s[len(s)/2:], c) // ส่งครึ่งหลังของ slice
x, y := <-c, <-c // รับผลลัพธ์จากทั้งสอง Goroutine
fmt.Println(x, y, x+y)
}
Goroutine เป็นเครื่องมือที่ทำให้การทำโปรแกรมที่รองรับหลายกระบวนการพร้อมกันใน Go เป็นไปได้อย่างง่ายดายและมีประสิทธิภาพ การศึกษาและทำความเข้าใจเรื่อง Goroutine อย่างลึกซึ้งจะช่วยเพิ่มศักยภาพในการพัฒนาโปรแกรมในยุคปัจจุบัน ที่ที่ข้อมูลต้องถูกประมวลผลอย่างรวดเร็วและพร้อมกัน
หากคุณสนใจเรียนรู้เพิ่มเติมเกี่ยวกับการเขียนโปรแกรมและการประยุกต์ใช้ Goroutine หรือเครื่องมืออื่น ๆ ใน Go การเข้าศึกษาที่ Expert-Programming-Tutor (EPT) อาจเป็นทางเลือกที่ดีสำหรับคุณ!
หมายเหตุ: ข้อมูลในบทความนี้อาจจะผิด โปรดตรวจสอบความถูกต้องของบทความอีกครั้งหนึ่ง บทความนี้ไม่สามารถนำไปใช้อ้างอิงใด ๆ ได้ ทาง EPT ไม่ขอยืนยันความถูกต้อง และไม่ขอรับผิดชอบต่อความเสียหายใดที่เกิดจากบทความชุดนี้ทั้งทางทรัพย์สิน ร่างกาย หรือจิตใจของผู้อ่านและผู้เกี่ยวข้อง
หากเจอข้อผิดพลาด หรือต้องการพูดคุย ติดต่อได้ที่ https://m.me/expert.Programming.Tutor/
Tag ที่น่าสนใจ: java c# vb.net python c c++ machine_learning web database oop cloud aws ios android
หากมีข้อผิดพลาด/ต้องการพูดคุยเพิ่มเติมเกี่ยวกับบทความนี้ กรุณาแจ้งที่ http://m.me/Expert.Programming.Tutor
085-350-7540 (DTAC)
084-88-00-255 (AIS)
026-111-618
หรือทาง EMAIL: NTPRINTF@GMAIL.COM
Copyright (c) 2013 expert-programming-tutor.com. All rights reserved. | 085-350-7540 | 084-88-00-255 | ntprintf@gmail.com