Setelah kemarin kita belajar bikin REST API pake Node.js, sekarang kita akan coba bikin REST API yang sama tapi pake Golang. Kita akan pake Gin framework yang terkenal dengan performanya yang cepet dan syntax yang simpel.
Persiapan
- Go sudah terinstall (minimal versi 1.16)
- Code editor (VS Code recommended + Go extension)
- Postman untuk testing API
- Basic knowledge Golang
1. Setup Project
Pertama, kita bikin project Go baru dan install dependencies yang dibutuhkan:
# Bikin folder project
mkdir go-rest-api
cd go-rest-api
# Inisialisasi Go module
go mod init go-rest-api
# Install Gin framework
go get -u github.com/gin-gonic/gin
2. Struktur Project
go-rest-api/
├── main.go
├── models/
│ └── book.go
├── go.mod
└── go.sum
3. Bikin Model
Buat file models/book.go
:
package models
type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
}
// Simulasi database dengan slice
var Books = []Book{
{ID: 1, Title: "Harry Potter", Author: "J.K. Rowling"},
{ID: 2, Title: "Lord of the Rings", Author: "J.R.R. Tolkien"},
}
4. Implementasi Main Server
Buat file main.go
:
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"go-rest-api/models"
)
func main() {
router := gin.Default()
// Routes akan ditambahkan di sini
router.Run(":8080")
}
5. Implementasi CRUD Endpoints
GET - Ambil Semua Buku
// Tambahkan di main.go
router.GET("/books", func(c *gin.Context) {
c.JSON(http.StatusOK, models.Books)
})
GET - Ambil Buku by ID
router.GET("/books/:id", func(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
for _, book := range models.Books {
if book.ID == id {
c.JSON(http.StatusOK, book)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
})
POST - Tambah Buku Baru
router.POST("/books", func(c *gin.Context) {
var newBook models.Book
if err := c.BindJSON(&newBook); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Set ID baru
newBook.ID = len(models.Books) + 1
models.Books = append(models.Books, newBook)
c.JSON(http.StatusCreated, newBook)
})
PUT - Update Buku
router.PUT("/books/:id", func(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
var updatedBook models.Book
if err := c.BindJSON(&updatedBook); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
for i, book := range models.Books {
if book.ID == id {
updatedBook.ID = id
models.Books[i] = updatedBook
c.JSON(http.StatusOK, updatedBook)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
})
DELETE - Hapus Buku
router.DELETE("/books/:id", func(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
for i, book := range models.Books {
if book.ID == id {
models.Books = append(models.Books[:i], models.Books[i+1:]...)
c.Status(http.StatusNoContent)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "Book not found"})
})
6. Middleware dan Validasi
Tambahkan validasi untuk request:
// Tambahkan struct tag untuk validasi
type Book struct {
ID int `json:"id"`
Title string `json:"title" binding:"required,min=1"`
Author string `json:"author" binding:"required,min=1"`
}
// Middleware untuk logging
router.Use(gin.Logger())
// Middleware untuk recovery dari panic
router.Use(gin.Recovery())
7. Testing dengan Postman
GET All Books
GET http://localhost:8080/books
POST New Book
POST http://localhost:8080/books
Body:
{ "title": "The Hobbit", "author": "J.R.R. Tolkien" }
Tips Performance
- Gunakan Gin di mode release untuk production
- Implementasi caching untuk data yang sering diakses
- Gunakan connection pooling saat integrasi dengan database
- Manfaatkan goroutines untuk operasi concurrent
8. Pengembangan Lebih Lanjut
Database Integration
Integrasi dengan GORM + PostgreSQL/MySQL
JWT Authentication
Implement jwt-go untuk secure endpoints
Unit Testing
Tambahkan test dengan package testing
API Documentation
Gunakan Swagger untuk dokumentasi API
Kenapa Pakai Gin?
- Performance yang sangat bagus
- Built-in middleware support
- Routing yang powerful
- Komunitas yang besar
Troubleshooting
package not found
Jalankan go mod tidy
untuk download dependencies
address already in use
Ganti port di router.Run() atau matikan aplikasi yang menggunakan port tersebut
Challenge!
Coba tambahkan fitur-fitur berikut:
- Implementasi search dengan query parameter
- Tambahkan pagination
- Implement rate limiting middleware
- Tambahkan file upload untuk cover buku