SoFunction
Updated on 2025-05-19

Detailed explanation of the HTTP server, client and middleware used by the Go language net/http package

Go language standard librarynet/httpThe package is very excellent and provides a very complete implementation of HTTP client and server. You can build a very simple HTTP server with just a few lines of code. Almost all web frameworks in the go language are encapsulation and modifications to existing http packages. Therefore, it is very important to master the http package before learning other frameworks.

HTTP Server

Let's first introduce the followingnet/httpUse of packages, through()and()Two functions can easily create a simple Go web server, the sample code is as follows:

package main
import (
    "fmt"
    "net/http"
)
func helloHandler(w , r *) {
    (w, "Hello, World!")
}
func main() {
    ("/hello", helloHandler)
    ("Server starting on port 8080...")
    (":8080", nil)
}

Routing processing

The http package provides two routing registration methods:

Processor Function (HandlerFunc)(pattern string, handler func(ResponseWriter, *Request))

func helloHandler(w , r *) {
    (w, "Hello, World!")
}
("/hello", helloHandler)

This form is the simplest and most direct, and is suitable for handling simple routing logic.The function will be converted toHandlerFuncType, it implementsHandlerinterface.

Processor object (Handler)(pattern string, handler Handler)

type CounterHandler struct {
    count int
}
func (h *CounterHandler) ServeHTTP(w , r *) {
    ++
    (w, "Visitor count: %d", )
}
handler := &CounterHandler{}
("/counter", handler)

ServeMux Routing

It is a multiplexer (router) provided by Go by default, which implementsHandlerInterface can be regarded as an advanced router manager. It works by:

  • When registering a route, store the path pattern and handler in the internal mapping
  • When receiving a request, find the corresponding processor according to the longest matching principle.
  • If the exact match is not found, it will try to find the path with slashes
  • In the end, no results are found, and an error of 404 will be returned.
mux := ()
("/products/", productsHandler)
("/articles/", articlesHandler)
("/", indexHandler)

Although this routing design is simple, it is sufficient for RESTful APIs and traditional web applications. For more complex needs, third-party routing libraries such as gorilla/mux can be considered.

HTTP Client

GET Request

resp, err := ("")
if err != nil {
    // Handle errors}
defer ()
body, err := ()
if err != nil {
    // Handle errors}
(string(body))

POST request

data := {}
("key", "value")
resp, err := ("/form", data)
if err != nil {
    // Handle errors}
defer ()
// Processing response...

Custom requests

req, err := ("GET", "", nil)
if err != nil {
    // Handle errors}
("Authorization", "Bearer token123")
("Content-Type", "application/json")
client := &{
    Timeout:  * 10,
}
resp, err := (req)
if err != nil {
    // Handle errors}
defer ()
// Processing response...

Middleware mode

Middleware is the key model for building modular HTTP services. Go's middleware is essentially a processor's wrapper function, which can add cross-cutting concern function without modifying the core business logic.

Basic middleware structure

func loggingMiddleware(next )  {
    return (func(w , r *) {
        start := ()
        // Call the next processor        (w, r)
        // Record request log        (
            "%s %s %s %v",
            ,
            ,
            ,
            (start),
        )
    })
}

The workflow for this model is:

  • The middleware receives a processor as a parameter
  • Return a new processor
  • The new processor adds additional functionality before and after executing the original logic

Middleware chain

Multiple middleware can form a processing chain in series:

func authMiddleware(next )  {
    return (func(w , r *) {
        if !isAuthenticated(r) {
            (w, "Unauthorized", )
            return
        }
        (w, r)
    })
}
func main() {
    mux := ()
    ("/secure", secureHandler)
    // Build middleware chain    handler := loggingMiddleware(authMiddleware(mux))
    (":8080", handler)
}

The execution order of middleware is from the outside to the inside, that is, the middleware registered first and then execute. In the above example, the request will be logged first and then authenticated.

Context delivery

Middleware is often used to pass values ​​between requests, and should be used at this time.

func requestIDMiddleware(next )  {
    return (func(w , r *) {
        // Generate a unique request ID        requestID := ().String()
        // Create a new context and store the request ID        ctx := ((), "requestID", requestID)
        // Set response header        ().Set("X-Request-ID", requestID)
        // Continue processing with new context        (w, (ctx))
    })
}
// Get the request ID in the processorfunc handler(w , r *) {
    requestID := ().Value("requestID").(string)
    (w, "Request ID: %s", requestID)
}

This method is thread-safe, avoids the problem of global variables, and is a recommended way to handle data transfer between requests in Go.

References:

Golang Chinese learning document Standard library http package

This is the article about the detailed explanation of the use of the Go language net/http package. This is the end of this article. For more related contents of the use of the Go language net/http package, please search for my previous articles or continue browsing the following related articles. I hope everyone will support me in the future!