Mastering Go’s net/http Package: A Practical Guide
An in‑depth guide to Go’s net/http package explains its role as a standard‑library solution for HTTP client and server tasks, shows how to import it, demonstrates GET, POST and custom requests, builds simple servers with routing, adds middleware, and outlines common use cases such as APIs and web crawlers.
Package Overview
net/http is a core Go standard‑library package that provides concise interfaces for HTTP client and server functionality, including request sending, response handling, routing, and middleware composition.
Installation and Import
Because it is part of the standard library, no external installation is required; you simply import \"net/http\".
Using net/http as an HTTP Client
GET request
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
// 发送 GET 请求
resp, err := http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
// 读取响应内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading body:", err)
return
}
// 输出响应内容
fmt.Println("Response Body:", string(body))
}The example uses http.Get to send a GET request, checks for errors, defers resp.Body.Close() to avoid leaks, reads the body with ioutil.ReadAll, and prints the response.
POST request
package main
import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
)
func main() {
// 准备发送的数据
data := []byte(`{"title": "foo", "body": "bar", "userId": 1}`)
// 发送 POST 请求
resp, err := http.Post("https://jsonplaceholder.typicode.com/posts", "application/json", bytes.NewBuffer(data))
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
// 读取响应内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading body:", err)
return
}
// 输出响应内容
fmt.Println("Response Body:", string(body))
}This snippet shows http.Post with a JSON payload, specifying the content type, wrapping the data in bytes.NewBuffer, and handling the response similarly to the GET example.
Custom request with headers
package main
import (
"fmt"
"net/http"
"io/ioutil"
"log"
)
func main() {
// 创建自定义请求
req, err := http.NewRequest("GET", "https://jsonplaceholder.typicode.com/posts", nil)
if err != nil {
log.Fatal(err)
}
// 设置请求头
req.Header.Set("Authorization", "Bearer my-token")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 读取响应内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
// 输出响应内容
fmt.Println("Response Body:", string(body))
}Here http.NewRequest creates a request object, req.Header.Set adds an Authorization header, and http.Client.Do sends the request, demonstrating full control over method, URL, headers, and body.
Using net/http as an HTTP Server
Simple server
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
func main() {
// 注册路由和处理函数
http.HandleFunc("/", handler)
// 启动 HTTP 服务器
fmt.Println("Starting server on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Error starting server:", err)
}
}The server registers a handler with http.HandleFunc and starts listening on port 8080 using http.ListenAndServe.
Routing multiple handlers
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About Us!")
}
func main() {
// 注册多个路由和处理函数
http.HandleFunc("/hello", helloHandler)
http.HandleFunc("/about", aboutHandler)
// 启动 HTTP 服务器
fmt.Println("Starting server on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Error starting server:", err)
}
}Multiple routes are registered with distinct handler functions, allowing the server to respond differently based on the request path.
Middleware
Logging middleware example
package main
import (
"fmt"
"net/http"
"time"
)
// 日志中间件
func logRequest(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
fmt.Printf("Request: %s %s, Duration: %v
", r.Method, r.URL.Path, time.Since(start))
})
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
}
func main() {
// 注册路由和处理函数
http.HandleFunc("/hello", helloHandler)
// 使用日志中间件
http.Handle("/hello", logRequest(http.HandlerFunc(helloHandler)))
// 启动 HTTP 服务器
fmt.Println("Starting server on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Error starting server:", err)
}
}The logRequest middleware wraps a handler, records the start time, calls the next handler, then logs the method, path, and duration, illustrating how to add cross‑cutting concerns.
Typical Application Scenarios
Building RESTful APIs that handle GET, POST, PUT, DELETE requests.
Developing simple web applications that serve dynamic pages.
Writing web crawlers or data‑scraping tools that fetch pages via HTTP.
Implementing client‑side API calls to interact with external services.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
