Pass context by creating a context.Context with context.WithCancel or context.WithTimeout and explicitly threading it as the first argument to every function in your call chain.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Thread ctx through your functions
result := doWork(ctx, data)
This ensures cancellation signals and deadlines propagate from the entry point down to the lowest-level operations.