A timeout limits how long an operation may wait before it is interrupted or reported as failed. Without one, an HTTP call can wait indefinitely when a server never answers. section 6.6.2
Apply timeouts deliberately:
- Configure an http.Client with Timeout, such as 5*time.Second; the zero default means no timeout. section 6.6.2
- Prefer an owned client over http.DefaultClient when application-wide mutation could produce conflicting behavior. section 6.6.2
- Give each remote call its own context and deadline when a service performs multiple downstream calls. section 10.6 section 10.6.3
- Cancel derived contexts with defer cancel(), and handle ctx.Done() so slow work returns context errors. section 10.6.3
Testing a slow database call
Wrap the repository call in context.WithTimeout(ctx, 100*time.Millisecond), then make a mock wait for two seconds or ctx.Done(). Expect context.DeadlineExceeded when the timeout wins. section 10.6.3
Listing 6.55 ecb.go: timeout example
// Client can call the bank to retrieve exchange rates.
type Client struct {
client http.Client #1
}
// NewBank builds a Client that can fetch exchange rates
// within a given timeout.
func NewClient(timeout time.Duration) Client { #2
return Client{
client: http.Client{Timeout: timeout},
}
}
// FetchExchangeRate fetches the ExchangeRate for the day and returns it.
func (c Client) FetchExchangeRate(
source, target money.Currency) (money.ExchangeRate, error) {
const path =
"http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"
resp, err := c.client.Get(path) #3
[...]
Shows a reusable client constructor that accepts a time.Duration and configures an http.Client for exchange-rate requests. section 6.6.2
Listing 10.32 create_test.go: Testing the timeout
func TestCreate(t *testing.T) {
// ...
"db timeout": {
db: func(ctl *minimock.Controller) *mocks.HabitCreatorMock {
db := mocks.NewHabitCreatorMock(ctl)
db.AddMock.Set(
func(ctx context.Context, habit habit.Habit) error {
select {
// This tick is longer than a database call
case <-time.Tick(2 * time.Second):
return nil
case <-ctx.Done():
return ctx.Err()
}
})
return db
},
expectedErr: context.DeadlineExceeded, #1
},
Shows a timeout test whose mock selects between a deliberately slow operation and the context's Done channel. section 10.6.3








