Awesome
Go Timeouts
An unresponsive service can be worse than a down one. It can tie up your entire system if not handled properly. All network requests should have a timeout.
Here’s how to add timeouts for popular Go packages. All have been tested. The default is no timeout, unless otherwise specified. Enjoy!
Also available for Ruby, Python, Node, and Rust
Packages
Standard library
github.com
- aws/aws-sdk-go
- aws/aws-sdk-go-v2
- bradfitz/gomemcache
- couchbase/gocb
- elastic/go-elasticsearch
- emersion/go-smtp
- gocql/gocql
- go-pg/pg
- go-redis/redis
- go-sql-driver/mysql
- opensearch-project/opensearch-go
Other
Standard Library
net
conn, err := net.DialTimeout(network, address, time.Second)
if err != nil {
// handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))
net/http
client := http.Client{
Timeout: time.Second,
}
net/smtp
conn, err := net.DialTimeout("tcp", address, time.Second)
if err != nil {
// handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))
if err != nil {
// handle error
}
client, err = smtp.NewClient(conn, host)
os/exec
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
err := exec.CommandContext(ctx, cmd).Run()
github.com
aws/aws-sdk-go
sess := session.Must(session.NewSession(&aws.Config{
HTTPClient: &http.Client{Timeout: time.Second},
}))
aws/aws-sdk-go-v2
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithHTTPClient(&http.Client{Timeout: time.Second}),
)
bradfitz/gomemcache
mc := memcache.New(host)
mc.Timeout = time.Second
couchbase/gocb
cluster, err := gocb.Connect(connStr, gocb.ClusterOptions{
TimeoutsConfig: gocb.TimeoutsConfig{
ConnectTimeout: time.Second,
KVTimeout: time.Second,
ViewTimeout: time.Second,
QueryTimeout: time.Second,
AnalyticsTimeout: time.Second,
SearchTimeout: time.Second,
ManagementTimeout: time.Second,
},
})
See the docs for defaults
elastic/go-elasticsearch
cfg := elasticsearch.Config{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Second,
}).DialContext,
ResponseHeaderTimeout: time.Second,
},
}
es, err := elasticsearch.NewClient(cfg)
emersion/go-smtp
conn, err := net.DialTimeout("tcp", address, time.Second)
if err != nil {
// handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))
if err != nil {
// handle error
}
client, err = smtp.NewClient(conn, host)
gocql/gocql
cluster := gocql.NewCluster(host)
cluster.ConnectTimeout = time.Second
cluster.Timeout = time.Second
Default: 600ms connect timeout, 600ms read timeout
go-pg/pg
db := pg.Connect(&pg.Options{
DialTimeout: time.Second,
ReadTimeout: time.Second,
WriteTimeout: time.Second,
})
go-redis/redis
rdb := redis.NewClient(&redis.Options{
DialTimeout: time.Second,
ReadTimeout: time.Second,
WriteTimeout: time.Second,
})
go-sql-driver/mysql
cfg := mysql.Config{
Timeout: time.Second,
ReadTimeout: time.Second,
WriteTimeout: time.Second,
}
db, err := sql.Open("mysql", cfg.FormatDSN())
opensearch-project/opensearch-go
cfg := opensearch.Config{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Second,
}).DialContext,
ResponseHeaderTimeout: time.Second,
},
}
client, err := opensearch.NewClient(cfg)
Other
go.mongodb.org/mongo-driver/mongo
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
Don’t see a library you use?
Let us know. Even better, create a pull request for it.
Running the Tests
git clone https://github.com/ankane/go-timeouts.git
cd go-timeouts
go mod tidy
To run all tests, use:
go test ./... -v
To run individual tests, use:
go test test/helper_test.go test/net_http_test.go -v