Go 语言 net/http 包使用之HTTP 服务器、客户端与中间件详解

 更新时间:2025年05月19日 09:43:17   作者:Chandler24  
Go 语言标准库中的net/http包十分的优秀,提供了非常完善的 HTTP 客户端与服务端的实现,仅通过几行代码就可以搭建一个非常简单的 HTTP 服务器,本文给大家介绍Go语言net/http包使用之HTTP服务器、客户端与中间件的操作,感兴趣的朋友一起看看吧

Go 语言标准库中的net/http包十分的优秀,提供了非常完善的 HTTP 客户端与服务端的实现,仅通过几行代码就可以搭建一个非常简单的 HTTP 服务器。几乎所有的 go 语言中的 web 框架,都是对已有的 http 包做的封装与修改,因此,十分建议学习其他框架前最好先行掌握 http 包。

HTTP服务器

我们先初步介绍以下net/http包的使用,通过http.HandleFunc()http.ListenAndServe()两个函数就可以轻松创建一个简单的Go web服务器,示例代码如下:

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

路由处理

http包提供了两种路由注册方式:

处理器函数(HandlerFunc)http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}
http.HandleFunc("/hello", helloHandler)

这种形式最为简单直接,适合处理简单的路由逻辑。http.HandleFunc内部会将函数转换为HandlerFunc类型,它实现了Handler接口。

处理器对象(Handler)http.Handle(pattern string, handler Handler)

type CounterHandler struct {
    count int
}
func (h *CounterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.count++
    fmt.Fprintf(w, "Visitor count: %d", h.count)
}
handler := &CounterHandler{}
http.Handle("/counter", handler)

ServeMux路由

http.ServeMux是Go默认提供的多路复用器(路由器),它实现了Handler接口,可以看作是一个高级的路由管理器。它的工作原理是:

  • 注册路由时,将路径模式(pattern)和处理器(handler)存储在内部映射中
  • 收到请求时,按照最长匹配原则查找对应的处理器
  • 如果找不到精确匹配,会尝试查找带斜杠的路径
  • 最终都找不到则返回404错误
mux := http.NewServeMux()
mux.HandleFunc("/products/", productsHandler)
mux.HandleFunc("/articles/", articlesHandler)
mux.HandleFunc("/", indexHandler)

这种路由设计虽然简单,但对于RESTful API和传统Web应用已经足够。对于更复杂的需求,可以考虑第三方路由库如gorilla/mux。

HTTP客户端

GET请求

resp, err := http.Get("https://example.com")
if err != nil {
    // 处理错误
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
    // 处理错误
}
fmt.Println(string(body))

POST请求

data := url.Values{}
data.Set("key", "value")
resp, err := http.PostForm("https://example.com/form", data)
if err != nil {
    // 处理错误
}
defer resp.Body.Close()
// 处理响应...

自定义请求

req, err := http.NewRequest("GET", "https://example.com", nil)
if err != nil {
    // 处理错误
}
req.Header.Add("Authorization", "Bearer token123")
req.Header.Add("Content-Type", "application/json")
client := &http.Client{
    Timeout: time.Second * 10,
}
resp, err := client.Do(req)
if err != nil {
    // 处理错误
}
defer resp.Body.Close()
// 处理响应...

中间件模式

中间件是构建模块化HTTP服务的关键模式。Go的中间件本质上是处理器的包装函数,可以在不修改核心业务逻辑的情况下,添加横切关注点功能。

基本中间件结构

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 %s %v",
            r.Method,
            r.URL.Path,
            r.RemoteAddr,
            time.Since(start),
        )
    })
}

这种模式的工作流程是:

  • 中间件接收一个处理器作为参数
  • 返回一个新的处理器
  • 新处理器在执行原有逻辑前后添加额外功能

中间件链

多个中间件可以串联形成处理链:

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !isAuthenticated(r) {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/secure", secureHandler)
    // 构建中间件链
    handler := loggingMiddleware(authMiddleware(mux))
    http.ListenAndServe(":8080", handler)
}

中间件的执行顺序是从外到内,即先注册的中间件后执行。上面的例子中,请求会先经过日志记录,再进行认证检查。

上下文传递

中间件常用于在请求间传递值,这时应该使用context.Context

func requestIDMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 生成唯一请求ID
        requestID := uuid.New().String()
        // 创建新上下文并存储请求ID
        ctx := context.WithValue(r.Context(), "requestID", requestID)
        // 设置响应头
        w.Header().Set("X-Request-ID", requestID)
        // 使用新上下文继续处理
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}
// 在处理器中获取请求ID
func handler(w http.ResponseWriter, r *http.Request) {
    requestID := r.Context().Value("requestID").(string)
    fmt.Fprintf(w, "Request ID: %s", requestID)
}

这种方式是线程安全的,避免了全局变量的问题,是Go中处理请求间数据传递的推荐方式。

参考资料:

Golang 中文学习文档 标准库 http包

到此这篇关于Go 语言 net/http 包使用之HTTP 服务器、客户端与中间件详解的文章就介绍到这了,更多相关Go 语言 net/http 包使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解golang中的闭包与defer

    详解golang中的闭包与defer

    闭包一个函数与其相关的引用环境组合的一个实体,其实可以理解为面向对象中类中的属性与方法,这篇文章主要介绍了golang的闭包与defer,需要的朋友可以参考下
    2022-09-09
  • Go语言中进行API限流的实战详解

    Go语言中进行API限流的实战详解

    API 限流是控制和管理应用程序访问量的重要手段,旨在防止恶意滥用、保护后端服务的稳定性和可用性,下面我们就来看看如何在Go语言中具体实现吧
    2025-01-01
  • Go语言结构体定义和使用方法

    Go语言结构体定义和使用方法

    这篇文章主要介绍了Go语言结构体定义和使用方法,以实例形式分析了Go语言中结构体的定义和使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 一文带你了解Go语言中的I/O接口设计

    一文带你了解Go语言中的I/O接口设计

    I/O 操作在编程中扮演着至关重要的角色,它涉及程序与外部世界之间的数据交换,下面我们就来简单了解一下Go语言中的 I/O 接口设计吧
    2023-06-06
  • Golang HTTP服务超时控制实现原理分析

    Golang HTTP服务超时控制实现原理分析

    这篇文章主要介绍了Golang HTTP服务超时控制实现原理,HTTP服务的超时控制是保障服务高可用性的重要措施之一,由于HTTP服务可能会遇到网络延迟,资源瓶颈等问题,因此需要对请求进行超时控制,以避免服务雪崩等问题,需要的朋友可以参考下
    2023-05-05
  • go select编译期的优化处理逻辑使用场景分析

    go select编译期的优化处理逻辑使用场景分析

    select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。接下来通过本文给大家介绍go select编译期的优化处理逻辑使用场景分析,感兴趣的朋友一起看看吧
    2021-06-06
  • Go 语言入门之net/url 包

    Go 语言入门之net/url 包

    这篇文章主要介绍了Go 语言入门之net/url 包,文章基于GO语言的相关资料展开 net/url 包的详细内容,具有一定的的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • GO如何模拟流操作实现示例探究

    GO如何模拟流操作实现示例探究

    这篇文章主要为大家介绍了GO如何模拟流操作实现示例探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Go语言的代码组织结构详细介绍

    Go语言的代码组织结构详细介绍

    这篇文章主要介绍了Go语言的代码码组织结构详细介绍,即Go语言源码的文件结构,本文讲解了包、main和main.main、os包等内容,需要的朋友可以参考下
    2014-10-10
  • go语言使用Chromedp实现二维码登陆教程示例源码

    go语言使用Chromedp实现二维码登陆教程示例源码

    这篇文章主要为大家介绍了go语言使用Chromedp实现二维码登陆示例源码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04

最新评论