HTTP Package in Go
The net/http package is one of the most powerful and important parts
of Go’s standard library.
It provides everything needed to build web servers, REST APIs, and HTTP clients
without external frameworks.
In this lesson, you will explore the HTTP package in depth and understand how real production systems use it.
What Is the net/http Package?
The net/http package allows Go programs to:
- Create HTTP servers
- Handle incoming requests
- Send HTTP requests to other services
- Work with headers, cookies, and status codes
It is designed to be simple, efficient, and highly performant.
Understanding HTTP Requests
An HTTP request contains:
- Method (GET, POST, PUT, DELETE)
- URL and query parameters
- Headers
- Optional body data
In Go, requests are represented using the *http.Request type.
Understanding HTTP Responses
Responses sent back to the client include:
- Status code
- Response headers
- Response body
Go uses http.ResponseWriter to write responses.
Creating a Custom HTTP Server
Instead of using the default server, you can create your own HTTP server configuration.
server := &http.Server{
Addr: ":8080",
Handler: nil,
}
server.ListenAndServe()
This allows full control over timeouts and server behavior.
Handling Routes with ServeMux
Go uses a request multiplexer (ServeMux) to route requests.
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/users", usersHandler)
http.ListenAndServe(":8080", mux)
This approach is commonly used in larger applications.
Working with Query Parameters
Query parameters are accessed using the request object.
func handler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
w.Write([]byte("Hello " + name))
}
For example, ?name=John returns “Hello John”.
Reading Headers
Headers contain metadata about the request.
userAgent := r.Header.Get("User-Agent")
fmt.Println(userAgent)
Headers are often used for authentication and content negotiation.
Setting Response Headers
You can add headers before writing the response body.
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
Serving JSON Responses
The HTTP package integrates seamlessly with JSON encoding.
json.NewEncoder(w).Encode(data)
This is standard practice for REST APIs.
Handling Request Bodies
POST and PUT requests often send data in the body.
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read body", http.StatusBadRequest)
return
}
Timeouts and Performance
Setting timeouts prevents slow clients from consuming server resources.
server := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
Using Middleware Pattern
Middleware allows executing logic before and after handlers.
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Request received")
next.ServeHTTP(w, r)
})
}
Creating an HTTP Client
The HTTP package can also send requests to external APIs.
resp, err := http.Get("https://api.example.com/data")
if err != nil {
panic(err)
}
defer resp.Body.Close()
Real-World Use Case
In production systems, the HTTP package is used to:
- Build microservices
- Communicate between services
- Expose APIs to frontend apps
- Handle authentication and security
Practice Exercises
Exercise 1
Create an endpoint that reads query parameters and returns JSON.
Exercise 2
Build a simple HTTP client that fetches data from an external API.
Key Takeaways
net/httpis production-ready- Handlers control request flow
- Headers and status codes matter
- Timeouts improve reliability
What’s Next?
In the next lesson, you will learn how to build REST API handlers with clean routing and reusable logic.