DEV Community

Weerasak Chongnguluam
Weerasak Chongnguluam

Posted on

Go time Sleep with cancellable with Context

#go

ฟังก์ชัน time.Sleep ใน Go เราใช้เพื่อหน่วงเวลาให้ goroutine ที่ฟังก์ชันนี้รันหยุดทำงานไปเป็นจำนวนเวลาเท่าที่เราใส่ให้ฟังก์ชันตอนเรียกใช้งาน

แต่ถ้าเกิดเราต้องการให้ time.Sleep นั้นถูกยกเลิกการ Sleep ก่อนเวลาที่เราส่งให้มัน เราต้องสร้าง Sleep ฟังก์ชันขึ้นมาเองแบบที่ยกเลิกได้

สิ่งที่ช่วยได้ก็คือ type Timer ซึ่งเรากำหนดค่า duration ให้กับมันแล้วมันก็จะส่ง signal ออกมาที่ channel C ซึ่งเป็น field นึงของ type Timer นั่นเอง

ดังนั้น ถ้าเวลาผ่านไปยังไม่ถึง duration ที่กำหนด แล้วเราไปพยายามเอาค่าออกมาจาก C มันก็จะหยุดเหมือน time.Sleep นั่นเอง

โค้ดแบบนี้ ทำหน้าที่เหมือน time.Sleep

func mySleep(d time.Duration) {
        timer := time.NewTimer(d)
        <-timer.C
}
Enter fullscreen mode Exit fullscreen mode

สิ่งที่ Timer มีมากกว่า Sleep คือมันมี method Stop ให้ยกเลิก Timer ก่อนเวลาที่กำหนดได้

ต่อไปเราจะทำให้ฟังก์ชัน SleepContext ของเรานั้นรับ context.Context เข้ามาด้วย เพื่อใช้เป็น signal ว่าเมื่อ context นั้นทำงานเสร็จ หรือยกเลิกแล้ว นั้นเราก็จะเรียก timer.Stop ด้วยนั่นเอง

โค้ดของ SleepContext ที่จะ Sleep และยกเลิกถ้า ctx นั้นถูกยกเลิกหรือ Done เรียบร้อยแล้ว

func SleepContext(ctx context.Context, d time.Duration) {
        timer := time.NewTimer(d)
        select {
        case <-ctx.Done():
                timer.Stop()
        case <- timer.C:
        }
}
Enter fullscreen mode Exit fullscreen mode

เราใช้ select statment เพื่อรอรับค่าจากทั้ง ctx.Done() หรือ timer.C อะไรมีค่ามาก่อนก็จบการทำงานของฟังก์ชัน แต่ถ้า ctx.Done() ก่อนก็ไม่ลืมที่จะยกเลิก timer ไปด้วย เพื่อไม่ให้มันยังทำงานทำให้เกิด memory leak อยู่จนกว่าจะหมดเวลา

ขอฝาก Buy Me a Coffee

สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง Buy Me a Coffee คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ

Buy Me A Coffee

Top comments (0)