Go

context.Background() vs context.TODO(): when do you use each, and why not pass nil?

Question 272MediumGo 1.22 to 1.25

Both return an empty context that is never canceled, has no deadline, and holds no values. They behave the same; the difference is intent, which static analysis tools and reviewers read:

  • Background(): the true root. Use it in main, init, tests, and top-level background daemons.
  • TODO(): "a context should be threaded here but isn't yet". It marks unfinished work during refactors, and you can grep for it.

Never pass nil, even if a function "doesn't use it". Calling any method on a nil interface panics, and WithCancel(nil) and friends panic with "cannot create context from nil parent". staticcheck SA1012 flags this.

// Handler deep inside a request: never use Background here
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context() // correct root for this request
	// ctx := context.Background() // BUG: loses cancellation, deadline, and trace IDs
	h.svc.Load(ctx, r.PathValue("id"))
}

Gotcha interviewers probe: calling context.Background() in the middle of a request path breaks the chain. Client disconnects are no longer noticed, timeouts no longer apply, and tracing loses its parent span.

More on Context

All 35 Context questions