WithDeadline และ WithValue
กำหนดเส้นตายแบบสัมบูรณ์และส่งค่าที่มีขอบเขตตามคำขอ
WithDeadline และ WithValue เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
context.WithDeadline
WithDeadline สร้างบริบทที่ยกเลิกเมื่อถึงเวลาสัมบูรณ์ที่กำหนด หากบริบทแม่มีกำหนดเวลาสิ้นสุดที่เร็วกว่านั้นอยู่แล้ว กำหนดเวลาของบริบทแม่จะมีผลเหนือกว่า
deadline := time.Now().Add(10 * time.Second)
ctx, cancel := context.WithDeadline(parent, deadline)
defer cancel()WithTimeout เทียบกับ WithDeadline
WithTimeout(parent, d) เทียบเท่ากับ WithDeadline(parent, time.Now().Add(d)) ให้ใช้ WithDeadline เมื่อมีเวลาหมดอายุแบบสัมบูรณ์ (เช่น จากส่วนหัว RPC ขาเข้า)
การอ่านกำหนดเวลา
ตรวจสอบกำหนดเวลาของบริบทใด ๆ ด้วย ctx.Deadline() ค่าบูลีนระบุว่ามีกำหนดเวลาหรือไม่
if deadline, ok := ctx.Deadline(); ok {
fmt.Println("expires at:", deadline)
}context.WithValue
WithValue ผูกคู่คีย์-ค่าเข้ากับบริบท โค้ดฝั่งถัดไปดึงค่าดังกล่าวด้วย ctx.Value(key)
type ctxKey string
const userKey ctxKey = "user"
ctx := context.WithValue(parent, userKey, currentUser)
func getUser(ctx context.Context) *User {
u, _ := ctx.Value(userKey).(*User)
return u
}การป้องกันคีย์ชนกัน
ใช้ชนิดเฉพาะแพ็กเกจที่ไม่ส่งออกสำหรับคีย์ เพื่อป้องกันการชนกันระหว่างแพ็กเกจ อย่าใช้ชนิดในตัว (string, int) เป็นคีย์บริบทโดยตรง
// Bad: string key can collide
ctx = context.WithValue(ctx, "user", u)
// Good: package-scoped type
type userKeyType struct{}
ctx = context.WithValue(ctx, userKeyType{}, u)สิ่งที่ควรจัดเก็บในบริบท
จัดเก็บเฉพาะค่าที่อยู่ในขอบเขตคำขอและข้ามขอบเขตเอพีไอ เช่น รหัสติดตาม โทเค็นการยืนยันตัวตน และรหัสคำขอ อย่าจัดเก็บอาร์กิวเมนต์ฟังก์ชันที่เป็นตัวเลือกหรือสถานะที่เปลี่ยนแปลงได้
ประสิทธิภาพของ WithValue
ctx.Value ค้นหาแบบเชิงเส้นย้อนขึ้นไปตามสายโซ่บริบท หลีกเลี่ยงการจัดเก็บหลายค่าในแต่ละบริบท หากมีหลายค่า ให้รวมค่าเหล่านั้นไว้ในโครงสร้างเดียว
type RequestMeta struct {
UserID int
TraceID string
}
type metaKey struct{}
ctx = context.WithValue(ctx, metaKey{}, RequestMeta{...})การส่งต่อค่าผ่านมิดเดิลแวร์
มิดเดิลแวร์ HTTP เป็นจุดมาตรฐานสำหรับแนบข้อมูลเมตาของคำขอเข้ากับบริบท และดึงข้อมูลดังกล่าวในตัวจัดการ:
func Auth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user := authenticate(r)
ctx := context.WithValue(r.Context(), userKey, user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}r.WithContext
แทนที่บริบทของคำขอ HTTP ด้วย r.WithContext(ctx) การดำเนินการนี้จะสร้างสำเนาแบบตื้นของคำขอพร้อมบริบทใหม่ โดยไม่แก้ไขคำขอเดิม
การส่งต่อกำหนดเวลา
เมื่อเกตเวย์กำหนดเวลาในบริบทและส่งคำขอต่อไปยังบริการถัดไป บริการทั้งหมดที่รับบริบทจะเคารพกำหนดเวลานั้นโดยอัตโนมัติ โดยไม่ต้องมีตรรกะหมดเวลาโดยเฉพาะ
สายโซ่ของบริบท
แต่ละ WithValue, WithCancel และ WithTimeout จะห่อบริบทแม่ไว้ในโหนดใหม่ ctx.Value จะไล่ไปตามสายโซ่จนกว่าจะพบคีย์หรือถึงบริบทต้นทางที่คืนค่า nil
ตรวจสอบความเข้าใจอย่างรวดเร็ว
เหตุใดคีย์บริบทจึงควรเป็นชนิดเฉพาะแพ็กเกจที่ไม่ส่งออก?
สรุป: WithDeadline และ WithValue
ประเด็นสำคัญ:
- WithDeadline ยกเลิกเมื่อถึงเวลาสัมบูรณ์ ส่วน WithTimeout ใช้เวลาแบบสัมพัทธ์
- ctx.Deadline() ใช้อ่านกำหนดเวลา
- ใช้ WithValue สำหรับข้อมูลเมตาที่อยู่ในขอบเขตคำขอ และใช้คีย์ที่มีชนิดและไม่ส่งออก
- รวมหลายค่าไว้ในโครงสร้างเดียวเพื่อลดความลึกของสายโซ่
คำถามที่พบบ่อย
บทเรียน “WithDeadline และ WithValue” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “WithDeadline และ WithValue” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “WithDeadline และ WithValue”
กำหนดเส้นตายแบบสัมบูรณ์และส่งค่าที่มีขอบเขตตามคำขอ คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “WithDeadline และ WithValue” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุผลที่มี context.Context
- WithCancel และ WithTimeout
- WithDeadline และ WithValue
- Context ในการเรียกใช้ HTTP และฐานข้อมูล