สร้าง REST API ด้วย Go และ Gin Framework
NPXVERSE Team•12 กรกฎาคม 2567•Web Development
GolangGinREST APIHTTP
การติดตั้ง Gin Framework
Gin เป็น HTTP web framework ที่เร็วและมีขนาดเล็กสำหรับ Go
การติดตั้ง
go mod init gin-api go get github.com/gin-gonic/gin
Basic HTTP Server
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { // สร้าง Gin router r := gin.Default() // Basic route r.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Hello, World!", "status": "success", }) }) // Start server on port 8080 r.Run(":8080") }
สร้าง CRUD API
ตัวอย่างการสร้าง API สำหรับจัดการข้อมูล Users
Data Models
package main import ( "net/http" "strconv" "github.com/gin-gonic/gin" ) type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` Age int `json:"age"` } // In-memory storage (ใช้ database จริงในการพัฒนาจริง) var users = []User{ {ID: 1, Name: "John Doe", Email: "john@example.com", Age: 30}, {ID: 2, Name: "Jane Smith", Email: "jane@example.com", Age: 25}, } var nextID = 3
GET All Users
func getUsers(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "data": users, "count": len(users), "message": "Users retrieved successfully", }) } // Route: GET /users r.GET("/users", getUsers)
GET User by ID
func getUserByID(c *gin.Context) { idParam := c.Param("id") id, err := strconv.Atoi(idParam) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid user ID", }) return } for _, user := range users { if user.ID == id { c.JSON(http.StatusOK, gin.H{ "data": user, "message": "User found", }) return } } c.JSON(http.StatusNotFound, gin.H{ "error": "User not found", }) } // Route: GET /users/:id r.GET("/users/:id", getUserByID)
POST Create User
type CreateUserRequest struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Age int `json:"age" binding:"required,min=1,max=120"` } 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: nextID, Name: req.Name, Email: req.Email, Age: req.Age, } users = append(users, newUser) nextID++ c.JSON(http.StatusCreated, gin.H{ "data": newUser, "message": "User created successfully", }) } // Route: POST /users r.POST("/users", createUser)
PUT Update User
func updateUser(c *gin.Context) { idParam := c.Param("id") id, err := strconv.Atoi(idParam) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid user ID", }) return } var req CreateUserRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } for i, user := range users { if user.ID == id { users[i].Name = req.Name users[i].Email = req.Email users[i].Age = req.Age c.JSON(http.StatusOK, gin.H{ "data": users[i], "message": "User updated successfully", }) return } } c.JSON(http.StatusNotFound, gin.H{ "error": "User not found", }) } // Route: PUT /users/:id r.PUT("/users/:id", updateUser)
DELETE User
func deleteUser(c *gin.Context) { idParam := c.Param("id") id, err := strconv.Atoi(idParam) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid user ID", }) return } for i, user := range users { if user.ID == id { users = append(users[:i], users[i+1:]...) c.JSON(http.StatusOK, gin.H{ "message": "User deleted successfully", }) return } } c.JSON(http.StatusNotFound, gin.H{ "error": "User not found", }) } // Route: DELETE /users/:id r.DELETE("/users/:id", deleteUser)
Middleware
Logging Middleware
func loggingMiddleware() gin.HandlerFunc { return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\" ", param.ClientIP, param.TimeStamp.Format("02/Jan/2006:15:04:05 -0700"), param.Method, param.Path, param.Request.Proto, param.StatusCode, param.Latency, param.Request.UserAgent(), param.ErrorMessage, ) }) } // ใช้ middleware r.Use(loggingMiddleware())
CORS Middleware
func corsMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) return } c.Next() } } r.Use(corsMiddleware())
Complete Example
package main import ( "fmt" "net/http" "strconv" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // Middleware r.Use(corsMiddleware()) // API Routes api := r.Group("/api/v1") { api.GET("/users", getUsers) api.GET("/users/:id", getUserByID) api.POST("/users", createUser) api.PUT("/users/:id", updateUser) api.DELETE("/users/:id", deleteUser) } // Health check r.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "healthy", "time": time.Now(), }) }) fmt.Println("Server starting on :8080") r.Run(":8080") }
การทดสอบ API
# GET all users curl http://localhost:8080/api/v1/users # GET user by ID curl http://localhost:8080/api/v1/users/1 # CREATE user curl -X POST http://localhost:8080/api/v1/users \ -H "Content-Type: application/json" \ -d '{"name":"Alice","email":"alice@example.com","age":28}' # UPDATE user curl -X PUT http://localhost:8080/api/v1/users/1 \ -H "Content-Type: application/json" \ -d '{"name":"John Updated","email":"john.updated@example.com","age":31}' # DELETE user curl -X DELETE http://localhost:8080/api/v1/users/1
Gin framework ทำให้การสร้าง REST API ใน Go เป็นเรื่องง่าย มีประสิทธิภาพสูง และมี features ครบครันสำหรับการพัฒนา web services