Go

What belongs in context values and what doesn't?

Question 270MediumGo 1.22 to 1.25

The official guidance: use context values only for request-scoped data that crosses process and API boundaries, not for passing optional parameters to functions.

Good fits: request/trace/span IDs, authenticated principal or tenant, deadline-related metadata, a request-scoped logger with fields already attached, and locale. These are cross-cutting data that middle layers pass along without looking at.

Bad fits:

  • Dependencies such as DB handles, config, or HTTP clients. These belong in struct fields or constructor parameters, where the compiler checks them.
  • Function parameters that affect business logic ("pageSize", "userID to delete"). Hiding them in context makes the API lie about what it needs, and a missing value turns a compile error into a runtime nil.
  • Mutable shared state, and anything large.
// Bad: hidden, untyped dependency
func DeleteUser(ctx context.Context) error {
	db := ctx.Value("db").(*sql.DB)       // panics if missing
	id := ctx.Value("userID").(int64)
	_, err := db.ExecContext(ctx, "DELETE FROM users WHERE id=$1", id)
	return err
}

// Good: explicit
func (s *Store) DeleteUser(ctx context.Context, id int64) error {
	_, err := s.db.ExecContext(ctx, "DELETE FROM users WHERE id=$1", id)
	return err
}

What the interviewer is looking for: a simple rule of thumb. If the function cannot work correctly without the value, it should be a parameter.

More on Context

All 35 Context questions