ทดลอง Native Coroutines ของ Python เมื่อนำมาเทียบกับ Goroutines ในภาษา Go
Mon, 8 February 2016 python golang

ในการพัฒนาระบบสารสนเทศในปัจจุบัน มีความต้องการความสามารถที่จะทำงานได้อย่างต่อเนื่อง หรือที่เรียกว่ามี Concurrent สูง ๆ ซึ่งเทคนิคที่นิยมใช้ในปัจจุบันคือการเขียนโปรแกรมแบบ Asynchronous ใน Python จะมีการเขียนโปรแกรมแบบ Asynchronous โดยการใช้ Coroutines ส่วนในภาษา Go จะใช้สิ่งที่เรียกว่า Goroutines ซึ่งผมได้ทดลองเขียนโค้ดตัวอย่างเพื่อเปรียบเทียบ การเขียนโปรแกรมแบบ Asynchronous ของทั้งสองภาษาดังนี้ครับ

1. การทดลอง Coroutines ใน Python

ผมได้เขียนโปรแกรมให้มีการเรียกฟังก์ชั่นต่อ ๆ กันไปโดยจะไม่มีการรอผลลัพธ์ซึ่งกันและกัน และให้แต่ละฟังก์ชั่นมีการจบการทำงานไม่พร้อมกัน โดยโค้ดมีดังนี้ครับ

File : a.py

import asyncio

async def go1():
    asyncio.gather(go2())
    asyncio.gather(go3())
    print("go1 running")
    await asyncio.sleep(5)
    print("go1 stoping")

async def go2():
    asyncio.gather(go4())
    print("go2 running")
    await asyncio.sleep(3)
    print("go2 stoping")

async def go3():
    print("go3 running")
    await asyncio.sleep(1)
    print("go3 stoping")

async def go4():
    print("go4 running")
    await asyncio.sleep(2)
    print("go4 stoping")

loop = asyncio.get_event_loop()
c = asyncio.gather(go1())
try:
    loop.run_until_complete(c)
finally:
    loop.close()

ส่วนผลลัพธ์จากการทำงานดังนี้ครับ

$ python a.py
go1 running
go2 running
go3 running
go4 running
go3 stoping
go4 stoping
go2 stoping
go1 stoping

2. การทดลอง Goroutines ในภาษา Go

ตัวอย่างโค้ดดังนี้ครับ

File : a.go

package main
import (
    "time"
    "fmt"
)

func go1() {
    go go2()
    go go3()
    fmt.Printf("go1 running\n")
    time.Sleep(5*time.Second)
    fmt.Printf("go1 stoping\n")
}

func go2() {
    go go4()
    fmt.Printf("go2 running\n")
    time.Sleep(3*time.Second)
    fmt.Printf("go2 stoping\n")
}

func go3() {
    fmt.Printf("go3 running\n")
    time.Sleep(time.Second)
    fmt.Printf("go3 stoping\n")
}

func go4() {
    fmt.Printf("go4 running\n")
    time.Sleep(2*time.Second)
    fmt.Printf("go4 stoping\n")
}

func main() {
    go go1()
    time.Sleep(6*time.Second)
}

ส่วนผลลัพธ์จากการทำงานดังนี้ครับ

$ go build a.go
$ ./a
go1 running
go3 running
go2 running
go4 running
go3 stoping
go4 stoping
go2 stoping
go1 stoping

ถึงแม้จะมีการโค้ดที่ต่างภาษากัน แต่แนวคิดคล้ายกันมาก ๆ เลยครับ :)

comments powered by Disqus