Goにおける「dial tcp: connect: connection refused」エラーの解決方法

beginner🔷 Go2026-06-10| Linux、macOS、またはWindows上で動作するGo (Golang)アプリケーション。主にPostgreSQL、MySQL、Redis、またはマイクロサービスが関与する環境。

Error Message

dial tcp 127.0.0.1:5432: connect: connection refused
#golang#networking#docker#postgresql#troubleshooting

エラーを読み解くgo run main.goを実行した際、アプリが起動する代わりにconnection refusedで終わる大量のテキストが表示されることがあります。イライラする瞬間ですが、このメッセージは実は非常に具体的です。Goのnetパッケージは、コードがターゲットIP(127.0.0.1など)を見つけることには成功したものの、転送先のOSが指定されたポート(5432など)でのリクエストを能動的に拒否した場合にこのエラーをスローします。

これは、有効な電話番号にダイヤルしたものの、相手がその特定の回線での通話を拒否しているために、すぐに電話を切られてしまうような状況だと考えてください。

接続が失敗する理由ほとんどの開発者がこの問題に直面する理由は、主に次の4つのいずれかです。

  • サービスが起動していない: データベース(PostgreSQL、Redisなど)が実際には動作していません。- ポート番号の間違い: ポート5432に接続しようとしていますが、サービスは実際には5433や8080で待機しています。- 隔離状態: サービスは動作していますが、ローカル・トラフィックのみを待機しており、別のネットワークインターフェースからのアクセスを拒否しています。- Dockerの罠: Goアプリがコンテナ内で動作しており、localhostがホストマシンではなくコンテナ自身を指しています。## ステップバイステップの修正方法### 1. サービスの状態を確認するまず、ターゲットとなるサービスが実際に稼働しているか確認してください。ポート5432でPostgreSQLを使用している場合は、すぐにその状態をチェックしましょう。サービスがクラッシュしているか、起動していないことが最も一般的な原因です。
# Linux (systemd) の場合
systemctl status postgresql

# macOS (Homebrew) の場合
brew services list

ステータスがinactive(停止中)またはstoppedとなっている場合は、起動してください。インストールされていない場合は、それが最初の解決すべき課題となります。

2. ポートとアドレスを監査するGoの接続文字列は、実際の状況と一致していますか?Goにおける標準的な接続試行は以下のようになります。

// TCPハンドシェイクの試行
conn, err := net.Dial("tcp", "127.0.0.1:5432")
if err != nil {
    log.Fatalf("接続に失敗しました: %v", err)
}

lsofを使用して、そのポートで実際に何かが待機しているか確認してください。出力が空の場合、どのサービスもそのポートを使用していません。

# ポート5432のリスナーを探す
sudo lsof -i :5432
# またはnetstatで素早く確認する
netstat -tuln | grep 5432

3. Dockerの「Localhost」ミステリーを解決するこれは現代の開発における最大の落とし穴です。GoのコードがDockerコンテナ内で実行されている場合、127.0.0.1はホストマシンではなく、コンテナ内部のループバックを指します。データベースはそのコンテナ内にはないため、接続は即座に失敗します。

OSに合わせて接続文字列を更新してください。

  • macOSおよびWindows: 127.0.0.1host.docker.internalに置き換えます。- Linux: ゲートウェイIP(通常は172.17.0.1)を使用するか、コンテナを--network="host"で実行してホストのネットワークスタックを共有します。### 4. バインドアドレスを確認するサービスの設定が原因の場合もあります。127.0.0.1でのみリッスンするように設定されていると、外部IPやDockerブリッジからのリクエストをすべて無視します。postgresql.confや同様の設定ファイルを確認してください。
# postgresql.conf
listen_addresses = 'localhost'  # 厳格:ローカルアプリのみ接続可能
listen_addresses = '*'          # 開放:任意のインターフェースからの接続を許可

これを'*'に変更した後、変更を反映させるためにサービスを再起動する必要があります。

5秒で修正を確認する修正をテストするために、Goアプリのコンパイルを待つ必要はありません。nc (netcat) を使用して、ポートが開いており、トラフィックを受け付けているか確認しましょう。

# 簡易的な疎通テスト
nc -vz 127.0.0.1 5432

接続に成功すると、Connection to 127.0.0.1 port 5432 [tcp/postgresql] succeeded!と表示されます。依然としてrefusedと表示される場合は、Goのコードではなく、ファイアウォールやサービスの設定に問題があります。

安定したアプリのためのプロのヒント- ハードコーディングを避ける: DB_HOST=127.0.0.1のような環境変数を使用しましょう。これにより、再コンパイルなしで本番用のURLに切り替えることができます。- リトライ処理を実装する: データベースの完全な初期化には5〜10秒かかることがよくあります。Goのリトライループを使用して、諦める前に3〜5回接続を試行するようにしましょう。- 起動を待機する: Docker Composeを使用している場合は、depends_onのヘルスチェックを使用して、Goのバイナリが起動する前にデータベースが正常であることを確認してください。

Related Error Notes