Go语言net/http库使用详解

作者:

文章目录
  • net/http是Go语言标准库中用于处理HTTP协议的核心组件,它提供了完整HTTP客户端和服务器实现。这个包让开发者能够快速构建高性能的Web服务,无需依赖第三方框架。
  • 以下是一个完整的用户管理API示例: package main import ( “encoding/json” “log” “net/http” “strconv” “time” “github.com/gorilla/mux” ) type User struct { ID int `json:”id”` Name string `json:”name”` Email string `json:”email”` } var users = []User{ {ID: 1, Name: “Alice”, Email: “alice@example.com”}, {ID: 2, Name: “Bob”, Email: “bob@example.com”}, } func getUsers(w http.ResponseWriter, r *http.Request) { w.Header().Set(“Content-Type”, “application/json”) json.NewEncoder(w).Encode(users) } func getUser(w http.ResponseWriter, r *http.Request) { w.Header().Set(“Content-Type”, “application/json”) params := mux.Vars(r) id, _ := strconv.Atoi(params[“id”]) for _, user := range users { if user.ID == id { json.NewEncoder(w).Encode(user) return } } http.Error(w, “User not found”, http.StatusNotFound) } func createUser(w http.ResponseWriter, r *http.Request) { var user User err := json.NewDecoder(r.Body).Decode(&user) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } user.ID = len(users) + 1 users = append(users, user) w.Header().Set(“Content-Type”, “application/json”) w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(user) } func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() next.ServeHTTP(w, r) log.Printf(“%s %s %v”, r.Method, r.URL.Path, time.Since(start)) }) } func main() { router := mux.NewRouter() // 路由定义 router.HandleFunc(“/users”, getUsers).Methods(“GET”) router.HandleFunc(“/users/{id}”, getUser).Methods(“GET”) router.HandleFunc(“/users”, createUser).Methods(“POST”) // 应用中间件 router.Use(loggingMiddleware) log.Println(“Server starting on :8080”) log.Fatal(http.ListenAndServe(“:8080”, router)) }
  • Go语言的net/http包提供了一个强大而灵活的工具集,用于构建HTTP客户端和服务器应用程序。通过本文的介绍,您应该能够: 创建基本的HTTP服务器和客户端 处理各种类型的HTTP请求和响应 实现中间件以增强功能 避免常见的陷阱和错误 构建生产级别的Web服务 net/http包的简洁设计和强大功能使得Go语言成为构建高性能Web服务的理想选择。随着对包的深入理解,您可以构建出既强大又易于维护的Web应用程序。 到此这篇关于Go语言net/http库使用详解的文章就介绍到这了,更多相关Go语言net/http库内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 详解Go语言中net/http包的使用 golang内置net/http包的使用详解 go标准库net/http服务端的实现示例 一文带你吃透Golang中net/http标准库服务端 Go语言使用net/http实现简单登录验证和文件上传功能 golang中的net/http库基本使用详解 一文详解Golang中net/http包的实现原理 Go 1.22对net/http包的路由增强功能详解 Go net/http的简单使用小结
  • 目录
    • 1 概述
      • 1.1 主要特性
    • 2 HTTP服务器开发
      • 2.1 基本服务器搭建
      • 2.2 处理不同的HTTP方法
      • 2.3 请求参数处理
        • 查询参数(URL参数)
        • 表单数据
        • JSON请求体
      • 2.4 路由管理
        • 使用ServeMux进行路由管理
        • 动态路由参数(需配合第三方路由库)
    • 3 HTTP客户端开发
      • 3.1 发送GET请求
        • 3.2 发送POST请求
          • 3.3 自定义请求
            • 3.4 客户端超时设置
            • 4 高级特性
              • 4.1 中间件开发
                • 4.2 静态文件服务
                  • 4.3 Cookie处理
                    • 4.4 JSON响应
                    • 5 常见问题与解决方案
                      • 5.1 易错点及避免方法
                        • 5.2 性能优化建议
                          • 5.3 安全最佳实践
                          • 6 实战案例:完整的API服务
                            • 7 总结

                              net/http是Go语言标准库中用于处理HTTP协议的核心组件,它提供了完整HTTP客户端和服务器实现。这个包让开发者能够快速构建高性能的Web服务,无需依赖第三方框架。

                              • 内置高性能HTTP服务器:直接支持并发请求处理
                              • 简洁的API设计:易于上手和使用
                              • 完整的HTTP协议支持:支持HTTP/1.x和HTTP/2
                              • 强大的路由机制:灵活的路由匹配和处理
                              • 中间件支持:可扩展的中间件架构

                              以下是创建一个最简单HTTP服务器的示例:

                              package main
                              
                              import (
                                  "fmt"
                                  "net/http"
                              )
                              
                              func main() {
                                  // 注册处理函数
                                  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                                      fmt.Fprint(w, "Hello, World!")
                                  })
                                  
                                  // 启动服务器
                                  fmt.Println("Starting server on :8080")
                                  err := http.ListenAndServe(":8080", nil)
                                  if err != nil {
                                      fmt.Printf("Error starting server: %vn", err)
                                  }
                              }
                              

                              可以根据请求方法执行不同的逻辑:

                              func handler(w http.ResponseWriter, r *http.Request) {
                                  switch r.Method {
                                  case http.MethodGet:
                                      fmt.Fprint(w, "This is a GET request.")
                                  case http.MethodPost:
                                      fmt.Fprint(w, "This is a POST request.")
                                  default:
                                      http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
                                  }
                              }
                              

                              func queryHandler(w http.ResponseWriter, r *http.Request) {
                                  name := r.URL.Query().Get("name")
                                  age := r.URL.Query().Get("age")
                                  fmt.Fprintf(w, "Hello, %s! Age: %s", name, age)
                              }
                              

                              func formHandler(w http.ResponseWriter, r *http.Request) {
                                  if r.Method == "POST" {
                                      err := r.ParseForm()
                                      if err != nil {
                                          http.Error(w, "Bad Request", http.StatusBadRequest)
                                          return
                                      }
                                      username := r.FormValue("username")
                                      password := r.FormValue("password")
                                      fmt.Fprintf(w, "Username: %s, Password: %s", username, password)
                                  }
                              }
                              

                              func jsonHandler(w http.ResponseWriter, r *http.Request) {
                                  type RequestData struct {
                                      Name  string `json:"name"`
                                      Email string `json:"email"`
                                  }
                                  
                                  var data RequestData
                                  err := json.NewDecoder(r.Body).Decode(&data)
                                  if err != nil {
                                      http.Error(w, err.Error(), http.StatusBadRequest)
                                      return
                                  }
                                  
                                  fmt.Fprintf(w, "Name: %s, Email: %s", data.Name, data.Email)
                              }
                              

                              func main() {
                                  mux := http.NewServeMux()
                                  
                                  mux.HandleFunc("/", homeHandler)
                                  mux.HandleFunc("/users", usersHandler)
                                  mux.HandleFunc("/posts", postsHandler)
                                  
                                  http.ListenAndServe(":8080", mux)
                              }
                              

                              虽然标准库的ServeMux不支持动态路由参数,但可以结合正则表达式或使用第三方库实现。

                              package main
                              
                              import (
                                  "fmt"
                                  "io"
                                  "net/http"
                              )
                              
                              func main() {
                                  resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
                                  if err != nil {
                                      fmt.Printf("Error: %vn", err)
                                      return
                                  }
                                  defer resp.Body.Close()
                                  
                                  body, err := io.ReadAll(resp.Body)
                                  if err != nil {
                                      fmt.Printf("Error reading body: %vn", err)
                                      return
                                  }
                                  
                                  fmt.Println(string(body))
                              }
                              

                              func main() {
                                  data := []byte(`{"title": "foo", "body": "bar", "userId": 1}`)
                                  
                                  resp, err := http.Post(
                                      "https://jsonplaceholder.typicode.com/posts",
                                      "application/json",
                                      bytes.NewBuffer(data),
                                  )
                                  if err != nil {
                                      fmt.Printf("Error: %vn", err)
                                      return
                                  }
                                  defer resp.Body.Close()
                                  
                                  // 处理响应...
                              }
                              

                              使用http.NewRequest可以创建更复杂的请求:

                              func main() {
                                  // 创建请求
                                  data := []byte(`{"name": "Go"}`)
                                  req, err := http.NewRequest("POST", "https://httpbin.org/post", bytes.NewBuffer(data))
                                  if err != nil {
                                      fmt.Printf("Error creating request: %vn", err)
                                      return
                                  }
                                  
                                  // 设置请求头
                                  req.Header.Set("Content-Type", "application/json")
                                  req.Header.Set("Authorization", "Bearer token123")
                                  
                                  // 发送请求
                                  client := &http.Client{
                                      Timeout: time.Second * 10,
                                  }
                                  
                                  resp, err := client.Do(req)
                                  if err != nil {
                                      fmt.Printf("Error sending request: %vn", err)
                                      return
                                  }
                                  defer resp.Body.Close()
                                  
                                  // 处理响应...
                              }
                              

                              func main() {
                                  client := &http.Client{
                                      Timeout: 10 * time.Second,
                                  }
                                  
                                  resp, err := client.Get("https://www.example.com")
                                  if err != nil {
                                      fmt.Printf("Error: %vn", err)
                                      return
                                  }
                                  defer resp.Body.Close()
                              }
                              

                              中间件可以在处理HTTP请求前后执行特定逻辑:

                              func loggingMiddleware(next http.Handler) http.Handler {
                                  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                                      start := time.Now()
                                      next.ServeHTTP(w, r)
                                      log.Printf("Request: %s %s processed in %v", 
                                          r.Method, r.URL.Path, time.Since(start))
                                  })
                              }
                              
                              func authMiddleware(next http.Handler) http.Handler {
                                  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                                      token := r.Header.Get("Authorization")
                                      if token != "valid-token" {
                                          http.Error(w, "Unauthorized", http.StatusUnauthorized)
                                          return
                                      }
                                      next.ServeHTTP(w, r)
                                  })
                              }
                              
                              func main() {
                                  mux := http.NewServeMux()
                                  mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                                      fmt.Fprint(w, "Hello, World!")
                                  })
                                  
                                  // 应用中间件
                                  handler := loggingMiddleware(authMiddleware(mux))
                                  
                                  http.ListenAndServe(":8080", handler)
                              }
                              

                              func main() {
                                  // 提供静态文件服务
                                  fs := http.FileServer(http.Dir("static"))
                                  http.Handle("/static/", http.StripPrefix("/static/", fs))
                                  
                                  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                                      fmt.Fprint(w, "Main page")
                                  })
                                  
                                  http.ListenAndServe(":8080", nil)
                              }
                              

                              func cookieHandler(w http.ResponseWriter, r *http.Request) {
                                  // 读取Cookie
                                  cookie, err := r.Cookie("session")
                                  if err != nil {
                                      // 创建新Cookie
                                      cookie = &http.Cookie{
                                          Name:     "session",
                                          Value:    "session-id-123",
                                          Path:     "/",
                                          HttpOnly: true,
                                      }
                                      http.SetCookie(w, cookie)
                                  }
                                  
                                  fmt.Fprintf(w, "Cookie value: %s", cookie.Value)
                              }
                              

                              func jsonResponseHandler(w http.ResponseWriter, r *http.Request) {
                                  type Response struct {
                                      Status  string `json:"status"`
                                      Message string `json:"message"`
                                      Data    interface{} `json:"data,omitempty"`
                                  }
                                  
                                  response := Response{
                                      Status:  "success",
                                      Message: "Data retrieved successfully",
                                      Data: map[string]interface{}{
                                          "id":   1,
                                          "name": "John Doe",
                                      },
                                  }
                                  
                                  w.Header().Set("Content-Type", "application/json")
                                  json.NewEncoder(w).Encode(response)
                              }
                              

                              易错点 问题描述 解决方案
                              资源泄露 未关闭响应体 总是使用defer resp.Body.Close()
                              路由冲突 路由匹配顺序错误 明确路由优先级,从具体到一般
                              阻塞操作 长时间运行的操作阻塞服务 使用goroutine处理耗时任务
                              内存泄漏 不当使用全局变量或缓存 合理管理资源生命周期

                              1. 连接复用:使用http.Client的默认连接池
                              2. 超时设置:为客户端和服务器设置合理的超时时间
                              3. 并发处理:利用Go的并发特性处理请求
                              4. 静态资源缓存:合理设置缓存头减少重复传输

                              func secureHeadersMiddleware(next http.Handler) http.Handler {
                                  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                                      // 设置安全相关的HTTP头
                                      w.Header().Set("X-Content-Type-Options", "nosniff")
                                      w.Header().Set("X-Frame-Options", "DENY")
                                      w.Header().Set("X-XSS-Protection", "1; mode=block")
                                      w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
                                      
                                      next.ServeHTTP(w, r)
                                  })
                              }
                              

                              以下是一个完整的用户管理API示例:

                              package main
                              
                              import (
                                  "encoding/json"
                                  "log"
                                  "net/http"
                                  "strconv"
                                  "time"
                                  
                                  "github.com/gorilla/mux"
                              )
                              
                              type User struct {
                                  ID    int    `json:"id"`
                                  Name  string `json:"name"`
                                  Email string `json:"email"`
                              }
                              
                              var users = []User{
                                  {ID: 1, Name: "Alice", Email: "alice@example.com"},
                                  {ID: 2, Name: "Bob", Email: "bob@example.com"},
                              }
                              
                              func getUsers(w http.ResponseWriter, r *http.Request) {
                                  w.Header().Set("Content-Type", "application/json")
                                  json.NewEncoder(w).Encode(users)
                              }
                              
                              func getUser(w http.ResponseWriter, r *http.Request) {
                                  w.Header().Set("Content-Type", "application/json")
                                  params := mux.Vars(r)
                                  id, _ := strconv.Atoi(params["id"])
                                  
                                  for _, user := range users {
                                      if user.ID == id {
                                          json.NewEncoder(w).Encode(user)
                                          return
                                      }
                                  }
                                  
                                  http.Error(w, "User not found", http.StatusNotFound)
                              }
                              
                              func createUser(w http.ResponseWriter, r *http.Request) {
                                  var user User
                                  err := json.NewDecoder(r.Body).Decode(&user)
                                  if err != nil {
                                      http.Error(w, err.Error(), http.StatusBadRequest)
                                      return
                                  }
                                  
                                  user.ID = len(users) + 1
                                  users = append(users, user)
                                  
                                  w.Header().Set("Content-Type", "application/json")
                                  w.WriteHeader(http.StatusCreated)
                                  json.NewEncoder(w).Encode(user)
                              }
                              
                              func loggingMiddleware(next http.Handler) http.Handler {
                                  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                                      start := time.Now()
                                      next.ServeHTTP(w, r)
                                      log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
                                  })
                              }
                              
                              func main() {
                                  router := mux.NewRouter()
                                  
                                  // 路由定义
                                  router.HandleFunc("/users", getUsers).Methods("GET")
                                  router.HandleFunc("/users/{id}", getUser).Methods("GET")
                                  router.HandleFunc("/users", createUser).Methods("POST")
                                  
                                  // 应用中间件
                                  router.Use(loggingMiddleware)
                                  
                                  log.Println("Server starting on :8080")
                                  log.Fatal(http.ListenAndServe(":8080", router))
                              }
                              

                              Go语言的net/http包提供了一个强大而灵活的工具集,用于构建HTTP客户端和服务器应用程序。通过本文的介绍,您应该能够:

                              1. 创建基本的HTTP服务器和客户端
                              2. 处理各种类型的HTTP请求和响应
                              3. 实现中间件以增强功能
                              4. 避免常见的陷阱和错误
                              5. 构建生产级别的Web服务

                              net/http包的简洁设计和强大功能使得Go语言成为构建高性能Web服务的理想选择。随着对包的深入理解,您可以构建出既强大又易于维护的Web应用程序。

                              到此这篇关于Go语言net/http库使用详解的文章就介绍到这了,更多相关Go语言net/http库内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

                              您可能感兴趣的文章:

                              • 详解Go语言中net/http包的使用
                              • golang内置net/http包的使用详解
                              • go标准库net/http服务端的实现示例
                              • 一文带你吃透Golang中net/http标准库服务端
                              • Go语言使用net/http实现简单登录验证和文件上传功能
                              • golang中的net/http库基本使用详解
                              • 一文详解Golang中net/http包的实现原理
                              • Go 1.22对net/http包的路由增强功能详解
                              • Go net/http的简单使用小结

                              站内搜索