time
time.Time และ time.Duration
หัวข้อที่มีชื่อว่า “time.Time และ time.Duration”Package time มี type หลักสองตัว:
time.Time— ช่วงเวลาหนึ่งที่มีความแม่นยำระดับ nanosecond พร้อม location (timezone) เสมอtime.Duration— signed 64-bit integer แทนความยาวของเวลาในหน่วย nanosecond ค่าคงที่อย่างtime.Hour,time.Minute,time.Secondและtime.Millisecondทำให้การคำนวณอ่านง่าย
d := 2*time.Hour + 30*time.Minute + 15*time.Secondfmt.Println(d) // 2h30m15sการสร้าง time.Time
หัวข้อที่มีชื่อว่า “การสร้าง time.Time”ในโค้ด production จะเรียก time.Now() เพื่อรับเวลาปัจจุบัน สำหรับการทดสอบและตัวอย่างที่ต้องการผลลัพธ์คงที่ให้ใช้ time.Date:
t := time.Date(2024, 1, 2, 15, 4, 5, 0, time.UTC)// year, month, day, hour, min, sec, nanosec, locationค่าของ time.Month (ตั้งแต่ time.January ถึง time.December) เป็น typed constant แต่ก็สามารถส่ง integer literal (1–12) ได้เพราะสามารถ assign ให้ time.Month ได้
การฟอร์แมต — reference layout
หัวข้อที่มีชื่อว่า “การฟอร์แมต — reference layout”Go ใช้ช่วงเวลาอ้างอิงที่เป็นรูปธรรมแทนรหัสฟอร์แมตแบบนามธรรมอย่าง YYYY-MM-DD ช่วงเวลาอ้างอิงคือ:
Mon Jan 2 15:04:05 MST 2006หากต้องการฟอร์แมตเวลา ให้เขียนช่วงเวลาอ้างอิงในรูปแบบที่ต้องการ:
t.Format("2006-01-02") // "2024-01-02"t.Format("15:04:05") // "15:04:05"t.Format("02 Jan 2006 15:04 MST") // "02 Jan 2024 15:04 UTC"t.Format(time.RFC3339) // "2024-01-02T15:04:05Z"การ Parse
หัวข้อที่มีชื่อว่า “การ Parse”time.Parse เป็นการทำงานตรงข้ามกับ Format — รับ layout และ string:
parsed, err := time.Parse("2006-01-02", "2024-06-15")// parsed คือเที่ยงคืน UTC ของวันที่ 15 มิถุนายน 2024string ของ layout ต้องตรงกับ component ของช่วงเวลาอ้างอิงที่ใช้ — ตัวอักษรเดียวกันในตำแหน่งเดียวกัน
การคำนวณ — Add และ Sub
หัวข้อที่มีชื่อว่า “การคำนวณ — Add และ Sub”deadline := t.Add(72 * time.Hour) // 3 วันต่อมาdiff := deadline.Sub(t) // time.Duration: 72h0m0sbefore := deadline.Before(t) // falseafter := deadline.After(t) // trueAdd รับ Duration และคืน Time Sub รับ Time สองค่าและคืน Duration ระหว่างทั้งสอง
package main
import ( "fmt" "time")
func main() { // Fixed time — deterministic in any interpreter t := time.Date(2024, 1, 2, 15, 4, 5, 0, time.UTC) fmt.Println(t)
// Formatting with the reference layout fmt.Println(t.Format("2006-01-02")) fmt.Println(t.Format("15:04:05")) fmt.Println(t.Format("Mon, 02 Jan 2006 15:04:05 MST")) fmt.Println(t.Format(time.RFC3339))
// Parsing parsed, err := time.Parse("2006-01-02", "2024-06-15") if err == nil { fmt.Println(parsed.Format("January 2, 2006")) }
// Arithmetic deadline := t.Add(72 * time.Hour) fmt.Println(deadline.Format("2006-01-02 15:04:05"))
diff := deadline.Sub(t) fmt.Println(diff)
// Duration construction d := 2*time.Hour + 30*time.Minute fmt.Println(d)
// Accessing date parts fmt.Println(t.Year(), t.Month(), t.Day()) fmt.Println(t.Hour(), t.Minute(), t.Second())}Loading Go runtime (first run only, ~8 MB)…
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| สิ่งที่ได้ | ประโยชน์ | ต้นทุน |
|---|---|---|
| time.Time เป็น value type | immutable, safe to copy และ share | ต้องระวัง timezone ที่แต่ละ Time carry |
| time.Duration (int64 nanoseconds) | arithmetic ชัดเจน — 5*time.Second | ต้อง multiply constant ชัดเจน ไม่ใช่แค่ “5” |
| time.After / time.NewTimer | สร้าง timeout ง่าย | time.After leak goroutine ใน tight loop — ควรใช้ time.NewTimer |
| reference layout (“2006-01-02”) | อ่านเข้าใจได้โดยดู example | ต่างจาก YYYY/MM/DD ของภาษาอื่น — ต้องจำ magic numbers |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- time.Now() return UTC เสมอ — ขึ้นกับ local timezone ของเครื่อง — ควรใช้ time.Now().UTC() เมื่อต้องการ UTC ชัดเจน
- time.Sleep(1*time.Second) precise — OS scheduler อาจ sleep นานกว่าที่กำหนด เช่น 1.05s — ไม่ใช่ hard real-time
- time.Equal เหมือน == — time.Equal เปรียบเทียบ instant ในเวลา (ignore timezone), == เปรียบเทียบ memory layout ทั้งหมดรวม timezone
- time.After ใน loop ไม่เป็นปัญหา — time.After สร้าง channel และ goroutine ใหม่ทุกครั้ง — ใน hot loop ใช้ time.NewTimer + Reset() แทน
💡 ตัวอย่างจากของจริง
Kubernetes: pod timeout, job deadline, lease expiry ล้วนใช้ time.Duration — เช่น
terminationGracePeriodSecondsคือtime.DurationPrometheus: scrape interval และ timeout ใช้ time.Duration — alerting rule duration เช่น “5m” parse ด้วย time.ParseDuration
Go HTTP server: http.TimeoutHandler ใช้ context + time.AfterFunc สำหรับ request timeout — ตัด connection เมื่อ handler ช้าเกินกำหนด