๐ฌ Golang Ticket Booking System from Scratch โ No Framework (Part 4)
๐ Booking Controller & HTTP Handler (main.go)
Setelah kita berhasil membangun logic utama BookingService dan mengamankan sistem dari race condition di Part 3, sekarang saatnya membuat sistem ini bisa diakses melalui HTTP API. Di part ini, kita akan membahas:
- Pembuatan Booking Controller untuk menerima HTTP request
- Penyusunan struct JSON untuk request dan response
- Konfigurasi HTTP server menggunakan
httprouter - Contoh testing via Postman atau Curl
๐ง Struktur Proyek Saat Ini
ticket-booking/
โโโ app/
โ โโโ database.go # Koneksi database
โโโ controller/
โ โโโ booking_controller.go # HTTP handler untuk booking
โโโ main.go # Entry point aplikasi
โโโ repository/
โ โโโ booking_repository.go # Akses query ke DB
โโโ request/
โ โโโ booking_request.go # Struct input request
โโโ response/
โ โโโ api_response.go # Struct response standar
โโโ service/
โ โโโ booking_service.go # Logika pemesanan kursi
โโโ go.mod1. Membuat Booking Controller
๐ File: controller/booking_controller.go
package controller
import (
"context"
"encoding/json"
"net/http"
"github.com/fardannozami/ticket-booking/helper"
"github.com/fardannozami/ticket-booking/request"
"github.com/fardannozami/ticket-booking/response"
"github.com/fardannozami/ticket-booking/service"
"github.com/julienschmidt/httprouter"
)
type BookingController interface {
BookSeat(writer http.ResponseWriter, req *http.Request, params httprouter.Params)
}
type bookingController struct {
bookingService service.BookingService
}
func NewBookingController(bookingService service.BookingService) BookingController {
return &bookingController{
bookingService: bookingService,
}
}
func (c *bookingController) BookSeat(writer http.ResponseWriter, req *http.Request, params httprouter.Params) {
var bookCreateRequest request.BookingCreateRequest
decoder := json.NewDecoder(req.Body)
err := decoder.Decode(&bookCreateRequest)
helper.PanicIfError(err)
_, err = c.bookingService.BookSeat(context.Background(), bookCreateRequest.EventId, bookCreateRequest.SeatId, bookCreateRequest.UserId)
helper.PanicIfError(err)
apiResponse := response.ApiResponse{
Code: http.StatusCreated,
Message: "created",
}
writer.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(writer).Encode(&apiResponse)
helper.PanicIfError(err)
}2. Membuat Struct Request dan Response
๐ File: request/booking_request.go
package request
type BookingCreateRequest struct {
EventId int `json:"event_id"`
SeatId int `json:"seat_id"`
UserId int `json:"user_id"`
}๐ File: response/api_response.go
package response
type ApiResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}3. Setup Koneksi Database
๐ File: app/database.go
package app
import (
"database/sql"
"github.com/fardannozami/ticket-booking/helper"
)
func NewSqlDb() *sql.DB {
db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/ticket-booking")
helper.PanicIfError(err)
return db
}4. Tambahkan Exception Handler
๐ File: exception/error_handler.go
package exception
import (
"encoding/json"
"net/http"
"github.com/fardannozami/ticket-booking/helper"
"github.com/fardannozami/ticket-booking/response"
)
func ErrorHandler(w http.ResponseWriter, r *http.Request, err interface{}) {
internalServerError(w, r, err)
}
func internalServerError(w http.ResponseWriter, r *http.Request, err interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
var message string
switch e := err.(type) {
case string:
message = e
case error:
message = e.Error()
default:
message = "Unknown error"
}
apiResponse := response.ApiResponse{
Code: http.StatusInternalServerError,
Message: "Internal Server Error",
Data: message,
}
encode := json.NewEncoder(w)
error := encode.Encode(&apiResponse)
helper.PanicIfError(error)
}5. Menjalankan HTTP Server
๐ File: main.go
package main
import (
"net/http"
"github.com/fardannozami/ticket-booking/app"
"github.com/fardannozami/ticket-booking/controller"
"github.com/fardannozami/ticket-booking/exception"
"github.com/fardannozami/ticket-booking/helper"
"github.com/fardannozami/ticket-booking/repository"
"github.com/fardannozami/ticket-booking/service"
_ "github.com/go-sql-driver/mysql"
"github.com/julienschmidt/httprouter"
)
func main() {
db := app.NewSqlDb()
bookingRepo := repository.NewBookingRepository()
bookingService := service.NewBookingService(db, bookingRepo)
bookingController := controller.NewBookingController(bookingService)
router := httprouter.New()
router.POST("/api/bookseat", bookingController.BookSeat)
router.PanicHandler = exception.ErrorHandler
server := http.Server{
Addr: ":3000",
Handler: router,
}
err := server.ListenAndServe()
helper.PanicIfError(err)
}๐งช Contoh Testing via Curl atau Postman
๐ธ Request (Booking Kursi)
curl -X POST http://localhost:3000/api/bookseat \
-H "Content-Type: application/json" \
-d '{
"event_id": 1,
"seat_id": 2,
"user_id": 12
}'โ Response Berhasil
{
"code": 201,
"message": "created",
"data": null
}โ Response Gagal (kursi sudah dibooking)
{
"code": 409,
"message": "seat already booked",
"data": null
}> ๐ Pastikan data event_id dan seat_id valid dan tersedia di database untuk testing ini.
๐ Summary
| Fitur | Status |
|---|---|
| BookingService | โ |
| Race Condition Handling | โ |
| JSON Request & Response | โ |
HTTP Routing (httprouter) | โ |
| Endpoint Booking Seat | โ |
๐ Tips Tambahan
Jika kamu ingin meningkatkan proyek ini lebih jauh, pertimbangkan untuk:
- Menambahkan validasi input menggunakan
go-playground/validator - Menyimpan konfigurasi ke
.envdan memuatnya menggunakanjoho/godotenv - Menambahkan middleware untuk logging atau recovery
- Menyusun error handling lebih rapi agar tidak semua pakai
PanicIfError
More Articles
You might also like
Mengenal Package io dan bufio di Golang
Selamat datang di tutorial keempat dari seri Golang Standard Library! Pada tutorial ini, kita akan membahas dua package penting dalam Golang, yaitu io dan bufio. Kedua package ini sangat berguna untuk operasi input/output (I/O) yang efisien dan mudah...
Doctor Booking App - Part 1
Halo! Pada kesempatan kali ini, saya akan membagikan proses awal pembuatan project Doctor Booking App menggunakan Laravel. Kita akan menggunakan beberapa tools modern seperti Livewire, Filament Admin, dan Pest untuk testing. Yuk langsung mulai! 1. Me...
Panduan Lengkap If-Else dan Switch dalam Golang
1. Pengenalan If-Else Dalam bahasa pemrograman Golang, if dan else digunakan untuk pengambilan keputusan dalam suatu program. Dengan if, kita bisa mengevaluasi suatu kondisi, dan berdasarkan hasilnya (benar atau salah), program akan mengeksekusi blok...