Gensics

Back to Home

สร้าง REST API ด้วย Go และ Gin Framework

NPXVERSE Team12 กรกฎาคม 2567Web 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