よくある質問
一般的な質問
開発中にライブリロードを有効にするには?
開発中の自動ライブリロードにはAirを使用します。Airはファイルを監視し、変更が検出されるとアプリケーションを自動的にリビルド/リスタートします。
Installation:
go install github.com/air-verse/air@latestSetup:
Create a .air.toml configuration file in your project root:
air initThen run air in your project directory instead of go run:
airAir will watch your .go files and automatically rebuild/restart your Gin application on changes. See the Air documentation for configuration options.
GinでCORSを処理するには?
公式のgin-contrib/corsミドルウェアを使用します:
package main
import ( "time"
"github.com/gin-contrib/cors" "github.com/gin-gonic/gin")
func main() { r := gin.Default()
// Default CORS configuration r.Use(cors.Default())
// Or customize CORS settings r.Use(cors.New(cors.Config{ AllowOrigins: []string{"https://example.com"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, AllowHeaders: []string{"Origin", "Content-Type", "Authorization"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: true, MaxAge: 12 * time.Hour, }))
r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{"message": "pong"}) })
r.Run()}For a complete security overview, see Security best practices.
静的ファイルを配信するには?
Use Static() or StaticFS() to serve static files:
func main() { r := gin.Default()
// Serve files from ./assets directory at /assets/* r.Static("/assets", "./assets")
// Serve a single file r.StaticFile("/favicon.ico", "./resources/favicon.ico")
// Serve from embedded filesystem (Go 1.16+) r.StaticFS("/public", http.FS(embedFS))
r.Run()}See Serving data from file for more details.
ファイルアップロードを処理するには?
Use FormFile() for single files or MultipartForm() for multiple files:
// Single file uploadr.POST("/upload", func(c *gin.Context) { file, _ := c.FormFile("file") c.SaveUploadedFile(file, "./uploads/"+file.Filename) c.String(200, "File %s uploaded successfully", file.Filename)})
// Multiple files uploadr.POST("/upload-multiple", func(c *gin.Context) { form, _ := c.MultipartForm() files := form.File["files"]
for _, file := range files { c.SaveUploadedFile(file, "./uploads/"+file.Filename) } c.String(200, "%d files uploaded", len(files))})See the Upload file documentation for more details.
JWTで認証を実装するには?
Use gin-contrib/jwt or implement custom middleware. Here’s a minimal example:
package main
import ( "net/http" "time"
"github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5")
var jwtSecret = []byte("your-secret-key")
type Claims struct { Username string `json:"username"` jwt.RegisteredClaims}
func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { tokenString := c.GetHeader("Authorization") if tokenString == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"}) c.Abort() return }
// Remove "Bearer " prefix if present if len(tokenString) > 7 && tokenString[:7] == "Bearer " { tokenString = tokenString[7:] }
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { return jwtSecret, nil })
if err != nil || !token.Valid { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) c.Abort() return }
if claims, ok := token.Claims.(*Claims); ok { c.Set("username", claims.Username) c.Next() } }}For session-based authentication, see Session management.
リクエストロギングを設定するには?
Gin includes a default logger middleware via gin.Default(). For structured JSON logging in production, see Structured logging.
For basic log customization:
r := gin.New()r.Use(gin.LoggerWithConfig(gin.LoggerConfig{ SkipPaths: []string{"/healthz"},}))r.Use(gin.Recovery())See the Logging section for all options including custom formats, file output, and skipping query strings.
グレースフルシャットダウンを処理するには?
See Graceful restart or stop for a complete guide with code examples.
”405 Method Not Allowed”の代わりに”404 Not Found”が返されるのはなぜ?
By default, Gin returns 404 for routes that don’t support the requested HTTP method. Set HandleMethodNotAllowed = true to return 405 instead:
r := gin.Default()r.HandleMethodNotAllowed = true
r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{"message": "pong"})})
r.Run()$ curl -X POST localhost:8080/ping
HTTP/1.1 405 Method Not AllowedAllow: GETクエリパラメータとPOSTデータを一緒にバインドするには?
Use ShouldBind() which automatically selects the binding based on content type:
type User struct { Name string `form:"name" json:"name"` Email string `form:"email" json:"email"` Page int `form:"page"`}
r.POST("/user", func(c *gin.Context) { var user User if err := c.ShouldBind(&user); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } c.JSON(200, user)})See the Binding section for all binding options.
リクエストデータをバリデーションするには?
Gin uses go-playground/validator for validation. Add validation tags to your structs:
type User struct { Name string `json:"name" binding:"required,min=3,max=50"` Email string `json:"email" binding:"required,email"` Age int `json:"age" binding:"gte=0,lte=130"`}
r.POST("/user", func(c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } c.JSON(200, gin.H{"message": "User is valid"})})See Binding and validation for custom validators and advanced usage.
Ginを本番モードで実行するには?
Set the GIN_MODE environment variable to release:
export GIN_MODE=release# orGIN_MODE=release ./your-appOr set it programmatically:
gin.SetMode(gin.ReleaseMode)Release mode disables debug logging and improves performance.
Ginでデータベース接続を処理するには?
See Database integration for a complete guide covering database/sql, GORM, connection pooling, and dependency injection patterns.
Ginハンドラをテストするには?
Use net/http/httptest to test your routes:
func TestPingRoute(t *testing.T) { router := gin.Default() router.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{"message": "pong"}) })
w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/ping", nil) router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code) assert.Contains(t, w.Body.String(), "pong")}See the Testing documentation for more examples.
パフォーマンスに関する質問
高トラフィック向けにGinを最適化するには?
- Use Release Mode: Set
GIN_MODE=release - Disable unnecessary middleware: Only use what you need
- Use
gin.New()instead ofgin.Default()for manual middleware control - Connection pooling: Configure database connection pools (see Database integration)
- Caching: Implement caching for frequently accessed data
- Load balancing: Use reverse proxy (nginx, HAProxy)
- Profiling: Use Go’s pprof to identify bottlenecks
- Monitoring: Set up metrics and monitoring to track performance
Ginは本番環境で使えますか?
はい。Ginは多くの企業で本番環境で使用されており、大規模な環境で実戦テスト済みです。本番環境でGinを使用しているプロジェクトの例についてはユーザーをご覧ください。
トラブルシューティング
ルートパラメータが動作しないのはなぜ?
Ensure route parameters use : syntax and are properly extracted:
// Correctr.GET("/user/:id", func(c *gin.Context) { id := c.Param("id") c.String(200, "User ID: %s", id)})
// Not: /user/{id} or /user/<id>See Parameters in path for details.
ミドルウェアが実行されないのはなぜ?
Middleware must be registered before routes or route groups:
// Correct orderr := gin.New()r.Use(MyMiddleware()) // Register middleware firstr.GET("/ping", handler) // Then routes
// For route groupsauth := r.Group("/admin")auth.Use(AuthMiddleware()) // Middleware for this group{ auth.GET("/dashboard", handler)}See Using middleware for details.
リクエストバインディングが失敗するのはなぜ?
Common reasons:
- Missing binding tags: Add
json:"field"orform:"field"tags - Content-Type mismatch: Ensure client sends correct Content-Type header
- Validation errors: Check validation tags and requirements
- Unexported fields: Only exported (capitalized) struct fields are bound
type User struct { Name string `json:"name" binding:"required"` // ✓ Correct Email string `json:"email"` // ✓ Correct age int `json:"age"` // ✗ Won't bind (unexported)}See Binding and validation for details.