Golang : ลำดับในการเรียกใช้งาน Goroutines 
Tags: go
Published: 2021-05-09 13:48:32

> **Goroutines** คือ ``Goroutines are functions or methods that run concurrently with other functions or methods.``

จากข้อความอันนี้ผมว่าก็น่าจะค่อนข้างชัดเจนระดับหนึ่งเลยซึ่งผมเลยคิดว่าไม่น่าจะต้องอธิบายเพิ่มแล้วนะครับ แต่ถ้าใครไม่เข้าใจ ผมแนะนำนี้เลยครับ [tour of go](https://tour.golang.org/concurrency/1)

## โจทย์วันนี้

พอผมได้ลองศึกษา การทำงานแบบ concurrent โดยใช้ goroutine และจากที่ผมได้เห็นตัวอย่างจากหลายๆ project พบว่ามีการเขียน run func ด้วย goroutines และใน function นั้นเองก็มีการเรียกใช้งาน anonymous function ด้วย goroutines จึงทำให้เริ่มส่งสัยว่า การเรียกใช้งานซ้อนๆกันแบบนี้ มันจะมีลำดับการทำงานยังไง

ผมก็เลยลองทำตัวอย่างง่ายๆเพื่อทดสอบ

## สมมติฐานเบื้องต้น

ผมเคยคิดว่ามันก็น่าจะทำงานตามลำดับในการเรียก อย่างเช่น goruntine ในสุดอาจจะต้องทำงานก่อนให้เสร็จแล้วค่อยมาทำในลำดับชั้นถัดไป ซึ่งไม่น่าจะทำงานพร้อมกัน บอกเลยครับก่อนจะทำทดสอบดู ก็คิดแบบนี้เลยแล้วพอไปอ่าน ตัวอย่าง project งง หนักเลย ^^

## เริ่มทดสอบกันหน่อย

```golang
func main() {
	...
	inputData := "123"

	go func1(inputData, startTime)

	go func2(inputData, startTime)

	//anonymous
	go func(s string) {go func3(s, startTime)}(inputData)
}

func func1(s string, startTime time.Time) {...}

func func2(s string, startTime time.Time) {...}

func func3(s string, startTime time.Time) {...}

```

ผมทำการสร้าง func เพื่อจำลองการทำงานทั้งหมด 4 function ซึ่งประกอบไปด้วย

**func main** จะเรียกใช้งาน func1, func2 นอกจากนี้ยังมีการสร้าง anonymous func ซึ่งจะใช้ในการ call func3 โดยทั้งหมดจะ run แบบ goroutine หรือก็คือให้ทั้งหมดมีการทำงานพร้อมกันนั้นเอง

เพื่อขยายความเข้าใจของคำว่าทำงานพร้อมกันผมจะลอง run program แบบไม่ใช่ goroutine ``หรือก็แค่ผมเอาคำว่า go ออกตอนเรียกใช้งาน function นั้นเอง``

**output run without goroutine**
```powershell
---- Start program ---- [0s] 
func1 output = 1      [10ms]
func1 output = 2      [20ms]
func1 output = 3      [30ms]
func2 output = 1      [40ms]
func2 output = 2      [50ms]
func2 output = 3      [60ms]
func3 output = 1      [70ms]
func3 output = 2      [80ms]
func3 output = 3      [90ms]
Anonymus-1 output = 1 [100ms]
Anonymus-1 output = 2 [110ms]
Anonymus-1 output = 3 [120ms]
---- End progra ---- [1.12s] 
```

จะเห็นว่าผลเป็นไปตามที่ผมคิดเลย ^^ 

ซึ่งก็คือจะทำงานตามลำดับในการเรียกใช้งานเลย และถ้าสังเกตุดีๆจะเห็นว่า func3 ที่ถูกเรียกโดย anonymus function จะมีการทำงานเรียกตามลำดับในการเรียก หรือการเขียน program แบบทั่วๆไปนั้นเอง

และคราวนี้ผมจะ run แบบใช้ goroutine

**output run with goroutine**
```powershell
---- Start program ---- [0s] 
func3 output = 1      [10ms]
Anonymus-1 output = 1 [10ms]
func1 output = 1      [10ms]
func2 output = 1      [10ms]
Anonymus-1 output = 2 [20ms]
func3 output = 2      [20ms]
func2 output = 2      [20ms]
func1 output = 2      [20ms]
func3 output = 3      [30ms]
Anonymus-1 output = 3 [30ms]
func1 output = 3      [30ms]
func2 output = 3      [30ms]
---- End progra ---- [1s] 
```

จากผลที่ได้เราจะเห็นว่า func1, func2, func3, Anonymus-1 นั้นจะทำงานพร้อมกันในทันที หรืออาจจะพูดได้ว่าแถบจะไม่สนใจลำดับในการเรียกใช้งานเลย ไม่ว่าจะเรียกโดยตรงจาก main หรือ ถูกเรียกจากอีก goroutine ก็คาม

Example project ซึ่งๆเพื่อนๆสามารถไปลองกันได้เลยครับ

[play.golang.org](https://play.golang.org/p/BUORJ0ftwKm)

อันนี้เป็นบทความที่ 2 ถ้าผมผิดพลาดยังไงเพื่อนๆสามารถแนะนำได้นะครับ

ขอบคุณครับ