π¬ 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
Golang Todolist CLI #3 β Menambahkan Command CLI Interaktif
Halo selamat datang kembali di seri Golang Todolist CLI bersama Ajitama! πSetelah sebelumnya kita membuat model Task dan repository-nya, sekarang saatnya membuat aplikasi kita bisa dikendalikan langsung dari terminal! Di seri ini kita akan: β Menamb...
Package strings dan strconv di Golang
Setelah sebelumnya membahas fmt, errors, os, dan flag, kali ini kita akan membahas dua package penting lainnya dalam standard library Go, yaitu strings dan strconv. Keduanya sangat berguna untuk memproses dan memanipulasi string dan konversi data β k...
Doctor Booking App β Part 2: Membuat Model dan Relasi Database
Setelah menyelesaikan setup awal di Part 1, kali ini kita akan mulai membangun struktur data untuk aplikasi booking dokter. Kita akan membuat beberapa model penting dan mendefinisikan relasi antar tabel melalui migration. 1. Generate Model & Migratio...