This is a RESTful API built in Go for managing a betting system. It allows users to place bets, settle bets, and check their balance. The service uses in-memory storage and ensures concurrency safety with mutexes. The API does not rely on external routing libraries, using the standard net/http package.
- Place a Bet: Users can place bets on events with specified odds and amounts.
- Settle a Bet: Admins can settle events, marking bets as won or lost and updating user balances.
- Check Balance: Users can query their current balance.
- Concurrency Safety: Uses mutexes to ensure thread-safe operations on in-memory data.
- Error Handling: Comprehensive error responses with appropriate HTTP status codes.
- Logging: Logs key actions (bet placement, settlement, errors) to stdout.
betting-api/
├── main.go # Entry point, sets up routes and server
├── api/
│ └── api.go # HTTP handlers for API endpoints
├── models/
│ └── models.go # Data structures (Bet, User)
├── storage/
│ └── storage.go # In-memory storage with concurrency safety
├── service/
│ └── service.go # Core logic
└── README.md # This documentation
- Go 1.24.1 or later
- Clone the repository or copy the code into a directory.
- Navigate to the project directory:
cd betengine - Run the application:
go run . - The server will start on
http://localhost:8080.
The API initializes with:
- Users:
user1(balance: 1000.0),user2(balance: 500.0) - Events:
event1(open),event2(open)
- Endpoint:
POST /api/bets/place - Description: Places a bet for a user on an event.
- Request Body:
{ "user_id": "string", "event_id": "string", "odds": float64, "amount": float64 } - Response:
- 201 Created:
{ "id": "string", "user_id": "string", "event_id": "string", "odds": float64, "amount": float64, "placed_at": "timestamp", "status": "pending" } - 400 Bad Request: Invalid input or insufficient balance.
- 404 Not Found: User not found.
- 201 Created:
- Example:
curl -X POST http://localhost:8080/api/bets/place -H "Content-Type: application/json" -d '{"user_id":"user1","event_id":"event1","odds":2.5,"amount":100}'
- Endpoint:
POST api/bets/settle - Description: Settles an event, updating all related bets and user balances.
- Request Body:
{ "event_id": "string", "result": "win" | "lose" } - Response:
- 200 OK:
{ "message": "Event settled" } - 400 Bad Request: Invalid event ID, result, or event already settled.
- 200 OK:
- Example:
curl -X POST http://localhost:8080/api/bets/settle -H "Content-Type: application/json" -d '{"event_id":"event1","result":"win"}'
- Endpoint:
GET /api/bets/balance?user_id=user1 - Description: Retrieves the balance for a specified user.
- Response:
- 200 OK:
{ "balance": float64 } - 404 Not Found: User not found.
- 200 OK:
- Example:
curl http://localhost:8080/api/balance?user_id=user1
Errors are returned in the following format:
{
"error": "error message"
}Common status codes:
400 Bad Request: Invalid input or request body.404 Not Found: Resource (user, event) not found.405 Method Not Allowed: Incorrect HTTP method.500 Internal Server Error: Unexpected server error (rare due to in-memory storage).
The API uses a sync.RWMutex to ensure thread-safe access to in-memory data:
- Write operations (placing bets, settling bets) acquire a write lock.
- Read operations (checking balance) acquire a read lock.
- In-Memory Storage: Data is not persisted; restarting the server resets all data.
- No Authentication: The API does not implement user authentication or authorization.
- Basic Routing: Uses standard
net/httprouting, which is less feature-rich than libraries like chi.
You can test the API using curl or tools like Postman. Example workflow:
- Check user balance:
GET /api/bets/balance?user_id=user1 - Place a bet:
POST /api/bets/place - Settle the event:
POST api/bets/settle - Check updated balance:
GET /api/bets/balance?user_id=user1
For automated testing, consider using Go's testing package or tools like Postman collections.