จากงาน GopherCon Singapore 2017 มี session อธิบายเกี่ยวกับการใช้งาน Context package
โดยที่ context นั้นสามารถส่งค่าต่าง ๆ ระหว่าง process ใน request scope
ซึ่งสามารถกำหนดค่าต่าง ๆ ใน context ได้ดังนี้
เช่น

  • withCancel()
  • withDeadline()
  • withTimeout()
  • withValue()

โดยตัวอย่างที่ใช้ context บ่อย ๆ คือการสื่อสารระหว่าง client-server
ตัวที่ชัดที่สุดคือ การใช้งาน context ร่วมกับ net/http package
ถ้าฝั่ง server ทำงานช้าเกินเวลาที่กำหนด
จะส่งสัญญาณยกเลิกการทำงานกลับมา

แต่มาเริ่มด้วย code ง่าย ๆ กันดีกว่า

เริ่มจาก code จำลองการทำงานของ function ที่ทำงานช้า ๆ

ทำงานตามลำดับกันดังนี้

ต่อมาลองคิดดูสิว่า ถ้าเจอปัญหาลักษณะนี้
แน่นอนว่า ไม่มีใครอยากรอไปเรื่อย ๆ
เพราะว่าเปลืองทั้งเวลา เปลืองทั้ง resource ที่ต้องใช้งาน
ดังนั้นสิ่งที่ต้องทำคือ การกำหนด Timeout

ถ้าเขียนด้วยภาษา Go นั้น

เราสามารถนำ buffered channel มาใช้จัดการได้ดังนี้

แต่ข้อเสียของวิธีการนี้คือ

ถ้าการทำงานของ goroutine ใช้ resource เยอะมาก ๆ
การรอจนกว่าจะ timeout น่าจะไม่มีประโยชน์อะไรเลย !!
เนื่องจากเปลือง resource อย่างมาก
เพราะว่าเรามั่นใจได้อย่างไรว่า roroutine มันถูกยกเลิกการทำงาน หรือ คืน resource ไปไหม ?
ดังนั้นสิ่งที่เราต้องการคือ ยกเลิกการทำงานของ goroutine นั้น ๆ (Cancelation)

คำถามคือ แล้วจะทำการยกเลิกอย่างไรดี ?
คำตอบคือ การใช้งาน context
โดย function ที่ทำงานจะต้องรับค่า context.Context เพิ่ม

โดยใน context นั้นเราสามารถกำหนดค่าได้เยอะ
จากตัวอย่างจะทำการกำหนด timeout เป็น 5 วินาที
ดังนั้นถ้า function ทำงานเกิน 5 วินาทีแล้ว
จะทำการยกเลิกการทำงานของ goroutine ทันทีดังนี้

เป็นวิธีการที่ดีกว่าทั้งสองแบบมาก ๆ
จัดการเรื่อง timeout ได้ง่ายขึ้น
จัดการเรื่อง การใช้งาน resource ได้ดีขึ้น

ขอให้สนุกกับการเขียน code

Resources
https://talks.golang.org/2014/gotham-context.slide#1
http://dahernan.github.io/2015/02/04/context-and-cancellation-of-goroutines/
https://www.linkedin.com/pulse/gos-context-library-explained-smita-vijayakumar

Tags: