backend
S
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
GoでゼロからHTTPサーバーを作る
Go標準ライブラリだけでHTTPサーバーを構築する方法を解説。ルーティング・ミドルウェア・JSON API・graceful shutdownまでをサンプルコード付きで紹介します。
一言結論
Go 1.22以降の標準ライブラリはメソッドとパスパラメータ付きルーティングをネイティブサポートし、フレームワークなしでも実用的なHTTP APIサーバーが構築できるレベルに達している。
Go の標準ライブラリで HTTP サーバーを作る
Go 1.22+ から net/http のルーティングが大幅に改善されました。フレームワークなしでも実用的な API サーバーが書けます。
最小限のサーバー
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
})
http.ListenAndServe(":8080", nil)
}
go run main.go
curl http://localhost:8080/hello # → Hello, World!
Go 1.22 の新ルーティング構文
mux := http.NewServeMux()
// メソッド + パスパターンで登録できるように
mux.HandleFunc("GET /users", listUsers)
mux.HandleFunc("POST /users", createUser)
mux.HandleFunc("GET /users/{id}", getUser) // パスパラメータ
mux.HandleFunc("DELETE /users/{id}", deleteUser)
パスパラメータの取得:
func getUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id") // Go 1.22 で追加
fmt.Fprintf(w, "User ID: %s", id)
}
JSON API を実装する
package main
import (
"encoding/json"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func listUsers(w http.ResponseWriter, r *http.Request) {
users := []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
// DB 保存処理(省略)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
ミドルウェアパターン
// ロギングミドルウェア
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}
// CORS ミドルウェア
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}
// 複数のミドルウェアをチェーン
func chain(h http.Handler, middlewares ...func(http.Handler) http.Handler) http.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
h = middlewares[i](h)
}
return h
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /users", listUsers)
handler := chain(mux, loggingMiddleware, corsMiddleware)
http.ListenAndServe(":8080", handler)
}
Graceful Shutdown
シグナルを受けてリクエストの処理中断なくシャットダウンします。
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// シグナル待受
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}
}()
log.Println("Server started on :8080")
<-quit
log.Println("Shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatal("Forced shutdown:", err)
}
log.Println("Server stopped")
}
まとめ
Go 1.22+ の標準ライブラリは、シンプルな REST API を作るのに十分な機能を持っています。外部フレームワーク(Gin・Echo・Chi)は高機能ですが、まず標準ライブラリを理解してから選択することを推奨します。
| 用途 | 推奨 |
|---|---|
| シンプルな API | 標準ライブラリ |
| ルーティングが複雑 | Chi |
| フル機能フレームワーク | Gin / Echo |