๐ฌ 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
Aplikasi Todo (CLI)
Tujuan Membuat aplikasi Command Line Interface (CLI) untuk mengelola daftar tugas langsung dari terminal. Contoh perintah dasar: tasks Fitur Utama Aplikasi harus mampu melakukan operasi CRUD pada data tugas yang disimpan dalam file. Operasi-operasi ...
Menginisiasi Project Golang
Pada seri Golang Basic, kita akan membahas cara menginisiasi atau membuat project Golang dari awal. Dalam ekosistem Golang, project sering disebut dengan module. Artikel ini akan membimbing Anda langkah demi langkah untuk memulai project Golang denga...
Tipe Data String, Boolean, dan Number di Golang
Golang (Go) adalah bahasa pemrograman yang dikembangkan oleh Google dan dikenal dengan kesederhanaan serta kecepatannya. Dalam pemrograman, tipe data sangat penting karena menentukan bagaimana sebuah nilai disimpan dan diproses dalam memori komputer....