Gin は Go 言語で実装された軸量込みで高性能な Web フレームワークです。RESTful API サーバーや Web アプリの開発に適しています。ここでは Gin の基本的な使い方を紹介します。
Gin の特徴
高性能
スレッドレスな HTTP リクエストを高速に処理します。
シンプルな API
ルーティングやミドルウェアが直感的で、視覚的に使いやすい。
ミドルウェア支援
ログ出力や認証などをカスタマイズした処理の結合が可能です。
コミュニティサポート
コミュニティが浸透しているため、問題が発生した時に情報を容易に採得できます。
インストール
下記コマンドを実行して Gin をインストールします。
go get -u github.com/gin-gonic/gin
go.mod にバージョン情報が追加されます。
require github.com/gin-gonic/gin v1.9.0
Gin の基本的な使い方
1. 最小構成のサーバ
これは Gin の最小構成の Web サーバーのコードです。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// デフォルトのエンジンを作成
router := gin.Default()
// ルート設定
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello, Gin!")
})
// 3000番ポートでサーバ起動
router.Run(":3000")
}
コード実行後、http://localhost:3000/ にアクセスすると「Hello, Gin!」が表示されます。
2. ルーティング
HTTP メソッドに対応したルートを設定します。
router.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
パスパラメータとクエリパラメータ
ルートのパラメータを簡単に取得できます。
// パスパラメータ
router.GET("/user/:id", func(c *gin.Context) {
id := c.Param("id")
c.String(http.StatusOK, "User ID: %s", id)
})
// クエリパラメータ
router.GET("/search", func(c *gin.Context) {
query := c.Query("q")
c.String(http.StatusOK, "Search query: %s", query)
})
3. JSON レスポンス
JSON 形式のレスポンスを返す例です。
router.GET("/json", func(c *gin.Context) {
data := gin.H{
"message": "hello",
"status": 200,
}
c.JSON(http.StatusOK, data)
})
gin.H は map[string]interface{} のシンタックスシュガーです。
ミドルウェア
1. 組み込みミドルウェア
Logger: ログ出力
Recovery: パニックが発生した際のエラー対処
2. カスタムミドルウェア
自分で定義するミドルウェアの例です。
func MyMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 前処理
c.Next()
// 後処理
}
}
func main() {
r := gin.Default()
r.Use(MyMiddleware())
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello, Middleware!")
})
r.Run(":3000")
}
グループルーティング
グループを使用すると、ルートを結合し、共通のパスやミドルウェアを適用できます。
func main() {
r := gin.Default()
api := r.Group("/api")
{
api.GET("/users", func(c *gin.Context) {
c.String(http.StatusOK, "GET /api/users")
})
api.POST("/users", func(c *gin.Context) {
c.String(http.StatusOK, "POST /api/users")
})
}
admin := r.Group("/admin", AuthMiddleware())
{
admin.GET("/dashboard", func(c *gin.Context) {
c.String(http.StatusOK, "Admin Dashboard")
})
}
r.Run(":3000")
}
テンプレートエンジン
HTML テンプレートをレンダリングする例です。
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "Main Page",
"message": "Hello, Gin Template!",
})
})
r.Run(":3000")
}
templates/index.html の例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{ .title }}</title>
</head>
<body>
<p>{{ .message }}</p>
</body>
</html>
CRUD 実装
シンプルな CRUD 操作を Gin で実装する例を紹介します。
モデル
type User struct {
ID int `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"},
}
エンドポイント
Create (追加)
router.POST("/users", func(c *gin.Context) {
var newUser User
if err := c.ShouldBindJSON(&newUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
newUser.ID = len(users) + 1
users = append(users, newUser)
c.JSON(http.StatusCreated, newUser)
})
Read (読み取り)
router.GET("/users", func(c *gin.Context) {
c.JSON(http.StatusOK, users)
})
router.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
for _, user := range users {
if strconv.Itoa(user.ID) == id {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
})
Update (更新)
router.PUT("/users/:id", func(c *gin.Context) {
id := c.Param("id")
var updatedUser User
if err := c.ShouldBindJSON(&updatedUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for i, user := range users {
if strconv.Itoa(user.ID) == id {
users[i] = updatedUser
users[i].ID = user.ID
c.JSON(http.StatusOK, users[i])
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
})
Delete (削除)
router.DELETE("/users/:id", func(c *gin.Context) {
id := c.Param("id")
for i, user := range users {
if strconv.Itoa(user.ID) == id {
users = append(users[:i], users[i+1:]...)
c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
})