HOME > 技術ドキュメント > Go Gin REST API 開発入門
Go 言語 Gin フレームワーク REST API 開発入門
Gin は Go 言語で最も広く使われている Web フレームワークの一つで、
標準ライブラリより高速なルーティングと、開発効率を高める豊富なユーティリティを提供します。
本ドキュメントでは Gin を使った REST API の基本構成から、バリデーション・ミドルウェア・DB 連携・テストまでを解説します。
1. プロジェクトの作成と Gin のインストール
mkdir myapi && cd myapi go mod init github.com/yourname/myapi # Gin と必要パッケージを追加 go get github.com/gin-gonic/gin go get github.com/gin-contrib/cors
2. 基本的なルーティング
Gin のルーティングは HTTP メソッドとパスを直接記述します。
// main.go
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
ID uint `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
}
func main() {
r := gin.Default() // Logger と Recovery ミドルウェアを含む
// ルートグループ
api := r.Group("/api/v1")
{
api.GET("/users", listUsers)
api.GET("/users/:id", getUser)
api.POST("/users", createUser)
api.PUT("/users/:id", updateUser)
api.DELETE("/users/:id", deleteUser)
}
r.Run(":8080")
}
func listUsers(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"users": users})
}
func getUser(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{"id": id})
}
3. JSON バインディングとバリデーション
ShouldBindJSON でリクエストボディを構造体にバインドします。
binding:"required" タグでバリデーションが自動的に行われます。
type CreateUserRequest struct {
Name string `json:"name" binding:"required,min=1,max=50"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"omitempty,gte=0,lte=150"`
}
func createUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
// バリデーションエラーを整形して返す
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
newUser := User{
ID: uint(len(users) + 1),
Name: req.Name,
Email: req.Email,
}
users = append(users, newUser)
c.JSON(http.StatusCreated, gin.H{"user": newUser})
}
クエリパラメータは c.Query / c.DefaultQuery で取得できます。
// GET /api/v1/users?page=1&limit=20
func listUsers(c *gin.Context) {
page := c.DefaultQuery("page", "1")
limit := c.DefaultQuery("limit", "20")
c.JSON(http.StatusOK, gin.H{"page": page, "limit": limit, "users": users})
}
4. ミドルウェア(ロギング・CORS・認証)
Gin のミドルウェアは r.Use() または グループ単位で適用できます。
import "github.com/gin-contrib/cors"
func main() {
r := gin.New()
// ロギングミドルウェア(カスタム)
r.Use(gin.LoggerWithFormatter(func(p gin.LogFormatterParams) string {
return fmt.Sprintf("[%s] %s %s %d %s\n",
p.TimeStamp.Format(time.RFC3339),
p.Method, p.Path, p.StatusCode, p.Latency)
}))
r.Use(gin.Recovery())
// CORS ミドルウェア
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"https://example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
}))
// 認証が必要なグループ
auth := r.Group("/api/v1")
auth.Use(authMiddleware())
{
auth.GET("/profile", getProfile)
}
r.Run(":8080")
}
// Bearer トークン認証ミドルウェアの例
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token != "Bearer valid-token" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return
}
c.Set("userID", 1)
c.Next()
}
}
5. GORM による PostgreSQL 接続
go get gorm.io/gorm go get gorm.io/driver/postgres
import (
"gorm.io/gorm"
"gorm.io/driver/postgres"
)
type User struct {
gorm.Model
Name string `gorm:"size:50;not null" json:"name"`
Email string `gorm:"uniqueIndex;not null" json:"email"`
}
func initDB() *gorm.DB {
dsn := "host=localhost user=myuser password=mypass dbname=mydb port=5432 sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal("DB 接続失敗:", err)
}
db.AutoMigrate(&User{})
return db
}
// ハンドラーで DB を使う例
func createUserDB(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user := User{Name: req.Name, Email: req.Email}
if result := db.Create(&user); result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "DB error"})
return
}
c.JSON(http.StatusCreated, user)
}
}
6. テスト(httptest)
// main_test.go
package main
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
func setupRouter() *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.Default()
r.GET("/api/v1/users", listUsers)
r.POST("/api/v1/users", createUser)
return r
}
func TestListUsers(t *testing.T) {
r := setupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/v1/users", nil)
r.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("期待: 200, 実際: %d", w.Code)
}
}
func TestCreateUser(t *testing.T) {
r := setupRouter()
body := `{"name":"Charlie","email":"charlie@example.com"}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/users", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
if w.Code != http.StatusCreated {
t.Errorf("期待: 201, 実際: %d, body: %s", w.Code, w.Body.String())
}
}
go test ./... -v
Gin API を HTTPS で本番運用する
本番環境では Nginx をリバースプロキシとして前段に置き、
SSL証明書で HTTPS 化することが標準的な構成です。
エスロジカルではデジサート・サイバートラストの正規取扱代理店として、
2009年から16年以上、RapidSSL 3,960円/1年(税込)〜でSSL証明書を販売しています。審査サポート・インストール代行も対応しています。
SSL証明書の購入はこちら / Nginx SSL/TLS 設定 / Go 言語 Web アプリ入門(net/http)
