How to Write an API in Golang (REST API Guide)
Overview
If you are looking for how to write API in Golang or how to create REST API in Golang, this knowledge base article provides a structured, production‑ready approach. It covers project setup, routing, request handling, middleware, database integration, testing, and best practices for building reliable services.
This guide explains how to build a basic Golang API and evolve it into a well‑structured RESTful service.
Quick Answer
To build a REST API in Golang, you typically:
- Initialize a Go module and project structure
- Choose an HTTP router (net/http, chi, gin, echo, etc.)
- Define routes and handlers
- Parse and validate requests
- Return structured JSON responses
- Add middleware (logging, recovery, CORS, authentication)
- Integrate a database (optional)
- Test endpoints and enforce error‑handling standards
Prerequisites
- Go installed on your system
- Basic understanding of HTTP methods (GET, POST, PUT, DELETE)
- A REST client such as Postman, Insomnia, or curl
Recommended Folder Structure
A clean structure helps scalability and maintainability.
my-api/
cmd/
server/
main.go
internal/
handler/
service/
repository/
pkg/
go.mod
Purpose of each layer:
- cmd/server: Application entry point
- internal: Private application logic
- handler: HTTP layer
- service: Business logic
- repository: Data access layer
Step 1: Initialize the Project
mkdir my-api && cd my-api
go mod init my-api
Step 2: Build a Basic Golang API Using net/http
This demonstrates how to build a basic Golang API using only the standard library.
package main
import (
"encoding/json"
"log"
"net/http"
)
type HealthResponse struct {
Status string `json:"status"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(HealthResponse{Status: "ok"})
}
func main() {
http.HandleFunc("/health", healthHandler)
log.Println("Server running on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Run the server:
go run ./cmd/server
Test endpoint:
curl http://localhost:8080/health
Step 3: Understanding REST API Design
REST APIs represent resources and operations using HTTP methods.
Common patterns:
- GET /users — Retrieve list of users
- POST /users — Create a new user
- GET /users/{id} — Retrieve a specific user
- PUT /users/{id} — Update a user
- DELETE /users/{id} — Delete a user
This structure is the foundation for how to write REST API in Golang.
Step 4: Use a Router for Production APIs
While net/http works, routers simplify route management and middleware handling.
Example using Chi router:
Install dependency:
go get github.com/go-chi/chi/v5
Sample usage:
r := chi.NewRouter()
r.Get("/health", healthHandler)
r.Get("/users", listUsers)
r.Post("/users", createUser)
http.ListenAndServe(":8080", r)
Step 5: JSON Request and Response Handling
Define request structures (DTOs):
type CreateUserRequest struct {
Email string `json:"email"`
Name string `json:"name"`
}
Typical handler responsibilities:
- Decode JSON request body
- Validate required fields
- Call business logic
- Return JSON response
Step 6: Standard Response Format (Best Practice)
Consistent response formats improve client integration.
Success Response
{
"data": { "id": "123", "email": "[email protected]" }
}
Error Response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "email is required"
}
}
Step 7: Middleware Integration
Essential middleware for most APIs:
- Request logging
- Panic recovery
- CORS support
- Authentication (JWT or API keys)
Example with Chi:
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
Step 8: Database Integration (Optional)
For CRUD operations, connect to a database such as PostgreSQL or MySQL.
Common options:
- database/sql with drivers
- pgx (PostgreSQL)
- gorm (ORM)
Keep database logic inside the repository layer to maintain separation of concerns.
Step 9: Calling External APIs from Golang
If your service needs to consume another REST API:
client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil)
resp, err := client.Do(req)
Parse JSON responses using json.NewDecoder(resp.Body).
Testing Your API
Recommended testing strategies:
- Unit testing handlers using httptest
- Integration testing with database
- Contract testing for external dependencies
Basic test flow:
- Create request using httptest.NewRequest
- Record response with httptest.NewRecorder
- Call handler
- Assert status code and response body
Common Mistakes to Avoid
- Inconsistent error responses
- Missing input validation
- Exposing internal errors to clients
- No request timeouts
- Mixing database logic inside handlers
Final
You now understand how to create API using Golang, how to build a Golang API, and how to write good API in Golang using REST principles. By following these practices, you can develop scalable, maintainable, and production‑ready backend services.
This approach works for both simple microservices and large distributed systems.
