Go言語でHTTPリクエストのタイムアウト設定を安全に行う方法|初心者向け完全ガイド
生徒
「Go言語でインターネット通信をするとき、ずっと待たされることがあるって聞いたんですが、本当ですか?」
先生
「あります。特にHTTP通信では、相手のサーバーが返事をしないと、プログラムが止まったままになることがあります。」
生徒
「それは困ります…。止まらないようにする方法はあるんですか?」
先生
「Go言語では、HTTPリクエストにタイムアウトを設定することで、安全に通信を制御できます。順番に見ていきましょう。」
1. HTTPリクエストとタイムアウトとは?
Go言語でAPI連携やネットワーク通信を行うときに使われるのがHTTPリクエストです。これは、ブラウザでWebサイトを見るときと同じ仕組みで、相手のサーバーに「情報をください」とお願いする動作です。
しかし、相手のサーバーが混んでいたり、ネットワークが不安定だったりすると、いつまでも返事が返ってこないことがあります。この「待てる最大時間」を決める仕組みがタイムアウトです。
タイムアウトを設定しないと、プログラムが止まったままになり、画面も動かず、エラーにも気づけません。初心者ほど、必ず設定しておきたい重要なポイントです。
2. タイムアウトを設定しないと起きる問題
タイムアウトがないHTTP通信は、電話をかけっぱなしで相手が出るまで永遠に待つ状態に似ています。相手が出なければ、こちらは何もできません。
Go言語のプログラムでも同じで、処理が止まり、次の処理に進めなくなります。WebサービスやAPI連携では、この状態が続くと、アプリ全体が動かなくなる原因になります。
そのため、Go言語でネットワーク通信を行うときは、「何秒待ってダメなら諦める」という判断をコードで書くことが大切です。
3. http.Getを使った基本的な通信の例
まずは、Go言語で一番シンプルなHTTP通信の例を見てみましょう。これは、指定したURLにアクセスする基本形です。
package main
import (
"net/http"
)
func main() {
http.Get("https://example.com")
}
このコードは短くて分かりやすいですが、実はタイムアウトが設定されていません。通信に時間がかかると、いつまでも待ち続けてしまいます。
4. http.Clientでタイムアウトを設定する方法
Go言語では、http.Clientという仕組みを使うことで、タイムアウトを簡単に設定できます。Clientは「通信の設定をまとめた箱」のようなものです。
package main
import (
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 5 * time.Second,
}
client.Get("https://example.com")
}
ここでは「5秒待って返事がなければ終了する」という意味になります。time.Secondは「1秒」を表すGo言語の部品です。
この方法は、初心者でも理解しやすく、安全なタイムアウト設定としてよく使われます。
5. タイムアウト時間はどれくらいが適切?
「何秒にすればいいのか分からない」という人も多いと思います。これは、用途によって変わります。
例えば、画面表示に使うAPIなら、3秒から5秒程度が一般的です。あまり長いと、利用者が「固まった」と感じてしまいます。
逆に、時間がかかっても問題ない処理なら、10秒以上にすることもあります。大切なのは、「待たせすぎない」意識を持つことです。
6. contextを使ったより安全なタイムアウト管理
Go言語には、contextという仕組みがあります。これは「この処理はここまで」という制限を伝えるための道具です。
package main
import (
"context"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
http.DefaultClient.Do(req)
}
この方法では、HTTP通信だけでなく、その周辺の処理もまとめて時間制限をかけられます。少し難しく見えますが、「3秒で終了する約束を作っている」と考えると理解しやすいです。
7. タイムアウト時のエラーを確認する考え方
タイムアウトが発生すると、Go言語ではエラーが返ってきます。これは「失敗」ではなく、「想定通りの結果」です。
エラーを正しく受け取り、「時間切れだった」と判断できれば、安全なプログラムになります。タイムアウトは、プログラムを守るための仕組みだと覚えておきましょう。
resp, err := http.Get("https://example.com")
if err != nil {
println("通信に失敗しました")
return
}
defer resp.Body.Close()
このように、エラーを確認する習慣をつけることが、Go言語でのAPI連携とネットワーク処理ではとても重要です。