🖥️ VS Code: Test API Langsung dari Editor
Install extension REST Client (oleh Huachao Mao) dari VS Code Extensions panel. Dengan REST Client, kamu bisa mengirim HTTP request langsung dari VS Code tanpa perlu app terpisah seperti Postman.
Buat file test.http di project lalu isi:
GET http://localhost:8080/users
###
POST http://localhost:8080/users
Content-Type: application/json
{ "nama": "Budi", "email": "budi@email.com" }
Klik "Send Request" yang muncul di atas setiap request untuk langsung melihat hasilnya.
Gin adalah web framework Go yang paling populer. Ringan, cepat, dan syntax-nya intuitif. Artikel ini membahas cara membangun REST API lengkap dari nol.
Setup Project
# Buat folder project
mkdir api-golang && cd api-golang
# Inisialisasi Go module
go mod init api-golang
# Install Gin
go get github.com/gin-gonic/gin
Server Dasar
// main.go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "API siap!",
})
})
r.Run(":8080") // localhost:8080
}
go run main.go
Routing
// HTTP methods
r.GET("/users", getUsers)
r.POST("/users", createUser)
r.PUT("/users/:id", updateUser)
r.DELETE("/users/:id", deleteUser)
r.PATCH("/users/:id", patchUser)
// Route groups
v1 := r.Group("/api/v1")
{
v1.GET("/users", getUsers)
v1.POST("/users", createUser)
}
// Route parameter
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id})
})
// Query parameter: /search?q=golang&page=1
r.GET("/search", func(c *gin.Context) {
q := c.Query("q")
page := c.DefaultQuery("page", "1")
c.JSON(200, gin.H{"q": q, "page": page})
})
JSON Request Body
// Definisi struct dengan tag json dan binding
type CreateUserRequest struct {
Nama string `json:"nama" binding:"required"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=6"`
}
func createUser(c *gin.Context) {
var req CreateUserRequest
// Bind + validasi otomatis
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// Proses data...
c.JSON(201, gin.H{
"message": "User berhasil dibuat",
"nama": req.Nama,
"email": req.Email,
})
}
CRUD Lengkap (In-Memory)
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type User struct {
ID int `json:"id"`
Nama string `json:"nama"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Nama: "Budi", Email: "budi@email.com"},
{ID: 2, Nama: "Sari", Email: "sari@email.com"},
}
var nextID = 3
// GET /users
func getUsers(c *gin.Context) {
c.JSON(http.StatusOK, users)
}
// GET /users/:id
func getUserByID(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
for _, u := range users {
if u.ID == id {
c.JSON(http.StatusOK, u)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User tidak ditemukan"})
}
// POST /users
func createUser(c *gin.Context) {
var input struct {
Nama string `json:"nama" binding:"required"`
Email string `json:"email" binding:"required"`
}
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user := User{ID: nextID, Nama: input.Nama, Email: input.Email}
users = append(users, user)
nextID++
c.JSON(http.StatusCreated, user)
}
// DELETE /users/:id
func deleteUser(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
for i, u := range users {
if u.ID == id {
users = append(users[:i], users[i+1:]...)
c.JSON(http.StatusOK, gin.H{"message": "User dihapus"})
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User tidak ditemukan"})
}
func main() {
r := gin.Default()
r.GET("/users", getUsers)
r.GET("/users/:id", getUserByID)
r.POST("/users", createUser)
r.DELETE("/users/:id", deleteUser)
r.Run(":8080")
}
Middleware
// Middleware autentikasi sederhana
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token != "Bearer secret-token" {
c.JSON(401, gin.H{"error": "Unauthorized"})
c.Abort() // hentikan request
return
}
c.Next() // lanjutkan ke handler berikutnya
}
}
// Pasang middleware pada grup route tertentu
protected := r.Group("/api")
protected.Use(AuthMiddleware())
{
protected.GET("/profile", getProfile)
protected.PUT("/profile", updateProfile)
}
💡 Response Helpers Gin
c.JSON(200, data) // JSON response
c.JSON(http.StatusOK, data) // pakai konstanta
c.JSON(http.StatusBadRequest, gin.H{...}) // gin.H = map[string]any
c.String(200, "Hello %s", nama) // plain text
c.Redirect(301, "/new-url") // redirect
Komentar 0