Go言語でリダイレクト処理を行う方法(http.Redirect)を初心者向けに解説
生徒
「先生、Webアプリでページを自動的に別のURLに移動させたいんですが、Go言語でどうやるんですか?」
先生
「その場合はhttp.Redirectを使うと簡単です。ブラウザに『ここに移動してください』と指示を出すイメージです。」
生徒
「リダイレクトって、どんな場面で使うんですか?」
先生
「例えばログイン後にトップページに移動させたり、古いURLから新しいURLに案内するときに使います。」
生徒
「なるほど、具体的な書き方を教えてください!」
1. http.Redirectの基本構文
Go言語でリダイレクト処理を行いたいときは、net/httpパッケージの
http.Redirectを使うのが定番です。
リダイレクトは「このURLではなく、別のURLへ移動してください」とブラウザに伝える仕組みで、
サーバー側から自動的にページ移動を指示できます。
ログイン後の画面遷移や、URL変更時の案内など、Webアプリでよく使われます。
http.Redirectは次の4つの引数を取ります(最初は名前だけでもOKです)。
wは返事を書き込むためのもの、rは今来ているリクエスト情報、
urlは移動先、statusは「どんなリダイレクトか」を表す番号だと思ってください。
http.ResponseWriter:レスポンスを書き込むためのオブジェクト(返事を書き込む先)*http.Request:現在のリクエスト情報(どこにアクセスされたか等)url string:移動先のURL(例:/newpage)status int:HTTPステータスコード(例:301, 302)
// 基本形:指定したURLへリダイレクトする
http.Redirect(w, r, "/newpage", http.StatusFound) // 302リダイレクト
この例では、ブラウザに「/newpageへ移動してください」と指示しています。
http.StatusFoundは302で、一時的なリダイレクトを意味します。
まずは「リダイレクト=ブラウザへの移動命令」という感覚をつかむと理解しやすいです。
ちなみに移動先は、/newpageのような相対パスでも、
https://example.comのような絶対URLでも指定できます。
初心者のうちは、同じサーバー内で移動させる相対パスから試すのがおすすめです。
package main
import (
"net/http"
)
// /go にアクセスされたら /newpage に移動させる最小サンプル
func redirectHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/newpage", http.StatusFound)
}
func newPageHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("新しいページです"))
}
func main() {
http.HandleFunc("/go", redirectHandler)
http.HandleFunc("/newpage", newPageHandler)
http.ListenAndServe(":8080", nil)
}
2. 一時的リダイレクトと恒久的リダイレクト
リダイレクトには大きく分けて2種類あります。 どちらも「別のURLへ移動してください」という指示ですが、意味合いが少し違います。 ここを押さえておくと、ログイン後の画面遷移やURL変更の対応がスムーズになります。
- 一時的リダイレクト(302):一時的に移動させたいときに使う(後で戻す可能性がある)
- 恒久的リダイレクト(301):URLが完全に変わったときに使う(今後は新URLが正)
迷いやすいポイントですが、初心者向けに言うと「302は仮の引っ越し」「301は本当に引っ越し」です。 たとえばログイン後に一度だけトップへ移動させるなら302が自然ですし、 古い記事URLを新しいURLに統一するなら301が向いています。 状況に合わない番号を使うと、意図しない動きになることがあるので注意しましょう。
// 302:一時的に別ページへ移動(ログイン後などでよく使う)
http.Redirect(w, r, "/temp", http.StatusFound)
// 301:URLが恒久的に変わった(古いURL→新URLへ案内)
http.Redirect(w, r, "/permanent", http.StatusMovedPermanently) // 301リダイレクト
恒久的リダイレクト(301)は、ブラウザや検索エンジンにも「このURLは今後こちら」という情報が伝わりやすいのが特徴です。 逆に、まだ試験運用中のページや一時的なメンテナンス案内などで301を使うと、あとで戻したいときに困ることがあります。 まずは「ログイン後などは302」「URLを正式に変更したら301」と覚えると分かりやすいです。
3. 実際にリダイレクト処理を作る例
ここでは、Go言語で実際にリダイレクト処理を行う最も基本的なサンプルを見ていきます。 「あるURLにアクセスされたら、別のURLへ自動的に移動させる」という流れを、 シンプルな構成で確認するのが目的です。 プログラミング未経験の方は、「URLと処理をひも付けている」くらいの理解で問題ありません。
この例では、/old という古いURLにアクセスされたときに、
新しいURLである /new へリダイレクトしています。
実際のWeb開発では、ページ構成の変更やURL整理の際によく使われるパターンです。
package main
import (
"fmt"
"net/http"
)
// 古いURL用のハンドラ
func oldHandler(w http.ResponseWriter, r *http.Request) {
// /old に来たら /new へ移動させる
http.Redirect(w, r, "/new", http.StatusMovedPermanently)
}
// 新しいURL用のハンドラ
func newHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "新しいページに移動しました!")
}
func main() {
http.HandleFunc("/old", oldHandler)
http.HandleFunc("/new", newHandler)
http.ListenAndServe(":8080", nil)
}
このプログラムを実行して http://localhost:8080/old にアクセスすると、
ブラウザは自動的に /new に移動します。
oldHandler では画面を表示せず、移動指示だけを出している点がポイントです。
リダイレクト処理は「画面を表示する前に移動を決める」役割だと覚えておくと理解しやすくなります。
4. リダイレクトを使うときの注意点
http.Redirectはとても便利ですが、使い方を間違えると
「ページが表示されない」「ずっと移動し続ける」といったトラブルにつながります。
ここでは、初心者のうちに必ず押さえておきたい注意点を整理します。
-
本文を書き込む前にリダイレクトする
リダイレクトはHTTPレスポンスのヘッダーで行われます。w.Writeやfmt.Fprintlnで本文を書いたあとにhttp.Redirectを呼ぶと、正しく動作しないことがあります。 -
無限リダイレクトに注意する
リダイレクト先が、再び同じ条件でリダイレクトされると、 ブラウザが「ループしている」と判断してページが開けなくなります。 -
ステータスコードを使い分ける
一時的な移動は302、URLが完全に変わった場合は301を使います。 なんとなくで選ばず、目的に合った番号を指定しましょう。 -
ユーザー入力をそのままURLに使わない
リクエストパラメータなどを直接リダイレクト先に使うと、 意図しないURLへ移動してしまう危険があります。
// NG例:本文を書いたあとにリダイレクトしている
func badHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("処理中です"))
http.Redirect(w, r, "/next", http.StatusFound) // 正しく動かない
}
このようなミスを防ぐためにも、 「リダイレクトは画面を表示する前に行う処理」 という意識を持っておくと安心です。 基本を守るだけで、多くのトラブルは回避できます。
5. 実務でよく使われるリダイレクトの活用シーン
ログイン処理後のリダイレクトや、古いブログ記事のURLを新しいURLに誘導する場合など、実務でもよく使われます。Go言語のhttp.Redirectを正しく理解しておくと、Webアプリのユーザー体験を向上させられます。
6. クエリパラメータ付きのURLへリダイレクトする
リダイレクト先のURLには、?key=value のようなクエリパラメータを付けることもできます。
たとえば「ログイン後に元のページへ戻す」「処理結果を画面に渡す」といった場面で便利です。
ただし、URLを文字列で手書きするとミスしやすいので、net/urlを使って組み立てると安全です。
package main
import (
"net/http"
"net/url"
)
func loginHandler(w http.ResponseWriter, r *http.Request) {
// /top?from=login のようにクエリ付きで移動させる
u := url.URL{Path: "/top"}
q := u.Query()
q.Set("from", "login")
u.RawQuery = q.Encode()
http.Redirect(w, r, u.String(), http.StatusFound)
}
func topHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("トップページです"))
}
func main() {
http.HandleFunc("/login", loginHandler)
http.HandleFunc("/top", topHandler)
http.ListenAndServe(":8080", nil)
}
この例では、/loginにアクセスすると/top?from=loginへリダイレクトします。
画面側ではクエリを見て「ログイン直後の表示」を出し分ける、といった使い方もできます。
まずは「URLに情報を付けて移動できる」ことを押さえておくと、実務のWeb開発で役立ちます。
7. リクエストパスに応じてリダイレクト先を切り替える
Webアプリでは、アクセスされたパスによって移動先を変えたいことがあります。
たとえば「古いURLを新しいURLへまとめて案内する」「末尾のスラッシュを揃える」などです。
このときは、r.URL.Pathを見て条件分岐し、適切なURLへリダイレクトします。
package main
import "net/http"
func legacyHandler(w http.ResponseWriter, r *http.Request) {
// どこにアクセスされたか(パス)を見て移動先を変える
switch r.URL.Path {
case "/old-about":
http.Redirect(w, r, "/about", http.StatusMovedPermanently) // 301
case "/old-contact":
http.Redirect(w, r, "/contact", http.StatusMovedPermanently) // 301
default:
http.Redirect(w, r, "/", http.StatusFound) // 302でトップへ
}
}
func main() {
http.HandleFunc("/old-about", legacyHandler)
http.HandleFunc("/old-contact", legacyHandler)
http.HandleFunc("/old-anything", legacyHandler)
http.ListenAndServe(":8080", nil)
}
このようにしておくと、古いリンクが残っていても新しいページへ自然に誘導できます。 リダイレクト先が増えてきたら、条件分岐を増やしすぎないように整理して管理するのがポイントです。
8. リダイレクトループを防ぐためのチェック方法
リダイレクトで意外と多いトラブルが「無限に移動し続けてページが開けない」状態です。 たとえば、移動先がまた同じ条件でリダイレクトしてしまうと、ブラウザ側でループと判断されます。 初心者のうちは、まず「今いるパスと移動先が同じになっていないか」を確認するだけでも効果があります。
package main
import "net/http"
func safeRedirect(w http.ResponseWriter, r *http.Request) {
to := "/new"
// すでに/newにいるならリダイレクトしない(ループ防止)
if r.URL.Path == to {
w.Write([]byte("ここが/newです"))
return
}
http.Redirect(w, r, to, http.StatusFound)
}
func main() {
http.HandleFunc("/old", safeRedirect)
http.HandleFunc("/new", safeRedirect)
http.ListenAndServe(":8080", nil)
}
この例では、/newにいるときは本文を返し、/oldのときだけ/newへ移動します。
リダイレクトを入れた直後に「移動先にも同じ処理が走っていないか」を確認するだけで、ループの事故はかなり減らせます。
まとめ
今回の記事では、Go言語(Golang)の標準パッケージであるnet/httpを使用した、Webアプリケーション開発に欠かせない「リダイレクト処理」について詳しく解説しました。
サーバー側からブラウザに対して特定のURLへの移動を指示するリダイレクトは、ユーザー体験を損なわずに適切なコンテンツへ誘導するための非常に強力なツールです。
http.Redirectの基本的な役割と仕組み
Go言語でリダイレクトを実装する際の基本は、http.Redirect関数を正しく呼び出すことです。
この関数は、レスポンスヘッダーに「Location」フィールドを書き込み、適切なHTTPステータスコードを添えてブラウザに返します。
初心者の方が特に意識すべきなのは、リダイレクトを実行するタイミングです。
HTMLの本文(レスポンスボディ)を書き込んだ後に呼び出しても動作しないため、必ずロジックの初期段階で実行するという「順序」を守ることが開発のポイントとなります。
適切なステータスコードの選定(301と302)
リダイレクトには、その目的によって使い分けるべき「ステータスコード」が存在します。 恒久的な移動を意味する301(StatusMovedPermanently)は、ドメイン移転やURLの完全な変更時に使用し、検索エンジンに対して「古いURLの評価を新しいURLに引き継ぐ」効果があります。 一方で、一時的な移動を意味する302(StatusFound)は、メンテナンス中やログイン後の自動遷移など、将来的に元のURLに戻る可能性がある場合や、一時的な処理の完了を知らせる際に適しています。 これらを適切に使い分けることで、検索エンジン最適化(SEO)の観点からも有利なWebサイトを構築できます。
実戦的なリダイレクトの実装テクニック
実際のプロジェクトでは、単にページを飛ばすだけでなく、複雑な条件分岐やデータの受け渡しが必要になる場面が多くあります。
例えば、クエリパラメータを付与して「どの画面から遷移してきたか」という情報を遷移先に伝える手法は、マーケティング分析やユーザー行動の追跡に役立ちます。
また、switch文を用いてリクエストパスごとに最適な遷移先を振り分ける実装は、大規模なサイト改修時のURLマッピングにおいて非常に重宝されます。
安全なリダイレクトと無限ループの回避
開発者が最も注意すべきは「無限リダイレクトループ」です。 AページからBページへ飛ばした先で、再びAページへ戻すような処理を書いてしまうと、ブラウザはエラーを表示して停止してしまいます。 これを防ぐには、現在のパスをチェックするガード条件を入れることや、リダイレクト先のURLが正しいかを事前に検証する習慣を身につけることが大切です。 安全で確実なコードを書くことが、信頼性の高いWebサービスの提供に繋がります。
応用:エラー発生時にトップページへリダイレクトするサンプル
最後に、実務でよく使われる「特定の条件下でエラーが発生した際、安全にトップページへ戻す」という応用的なコードサンプルを紹介します。 条件分岐とステータスコードの使い分けを再確認しましょう。
package main
import (
"net/http"
)
// 認証チェックを模したハンドラ
func secureHandler(w http.ResponseWriter, r *http.Request) {
// 本来はセッション確認などを行う
isLoggedIn := false
if !isLoggedIn {
// ログインしていない場合は一時的なリダイレクト(302)でログインページへ
// URLに「reason」というパラメータを付けて状況を伝える
http.Redirect(w, r, "/login?reason=auth_required", http.StatusFound)
return
}
w.Write([]byte("認証済みの秘匿コンテンツです"))
}
func loginPageHandler(w http.ResponseWriter, r *http.Request) {
reason := r.URL.Query().Get("reason")
if reason == "auth_required" {
w.Write([]byte("ログインが必要です。"))
} else {
w.Write([]byte("ログインページ"))
}
}
func main() {
http.HandleFunc("/secure", secureHandler)
http.HandleFunc("/login", loginPageHandler)
// サーバー起動
http.ListenAndServe(":8080", nil)
}
このように、Go言語のhttp.Redirectはシンプルながらも、Webサイトの導線を整理するための極めて重要な機能です。
公式ドキュメントや今回のサンプルを参考に、まずはローカル環境で様々なURLパターンを試してみてください。
一つひとつの挙動を理解することで、より高度なWebアプリケーションエンジニアへと成長できるはずです。
生徒
先生、Go言語でのリダイレクトについて詳しく教えていただきありがとうございました!
http.Redirect一行だけでページが移動するなんて、思っていたよりもずっとシンプルで驚きました。
これなら、自分のアプリでもすぐに実装できそうです。
先生
そうですね。Go言語は「シンプルであること」を大切にしている言語なので、標準機能だけでこれだけのことが簡単にできるようになっています。 ただ、使い方は簡単ですが、「なぜリダイレクトさせるのか」という意図に合わせてステータスコードを使い分けることが、プロのエンジニアとしての第一歩ですよ。
生徒
301と302の違いですね! 「301は永久的な引っ越し」「302は仮の移動」という説明がとても分かりやすかったです。 SEOにも影響するなんて、単なる画面遷移以上の意味があるんですね。
先生
その通りです。検索エンジンは、そうした細かい番号を見てサイトの構造を理解しようとします。 それから、注意点でお話しした「本文を書く前にリダイレクトする」というルールは守れそうですか?
生徒
はい!「手紙を出す前に封筒に行き先を書く」みたいなイメージですね。 本文を書き始めちゃうと、もうブラウザには「このページのデータが来るぞ」と伝わってしまうので、後から行き先を変えることはできない……という理解で合っていますか?
先生
素晴らしい例えです!その通りです。 HTTPプロトコルはヘッダーが先に来て、その後にボディが続くという構造になっていますからね。 無限ループのチェックも、最初は忘れがちですが、開発中に一度は経験する道かもしれません。もしページが開かなくなったら、まずは自分のリダイレクト条件を疑ってみてください。
生徒
気をつけます! まずはログイン判定からのリダイレクトを自分のプロジェクトに入れてみて、動作を確認してみようと思います。 クエリパラメータを使って、ログイン後の挨拶を出し分けるのにも挑戦してみたいです。
先生
ぜひやってみてください。 実際に動くものを作ると、理解がより一層深まります。 エラーを恐れずに、どんどんコードを書いて実験していきましょう。応援していますよ!
【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導
「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。
本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。
具体的な開発内容と環境
【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。
【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。
この60分で得られる3つの理解
「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。
データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。
ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。
※本講座は、将来的にバックエンドエンジニアやクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。
初めてのGo言語を一緒に学びましょう!