编程 Go语言中的`net/http`包,涵盖了HTTP请求和响应的基本概念

2024-11-19 09:48:17 +0800 CST views 567

概述

net/http 包可以处理 HTTP 协议,包括 HTTP 服务器和 HTTP 客户端。http 包主要由五个部分组成:

  • Request:HTTP 请求对象
  • Response:HTTP 响应对象
  • Client:HTTP 客户端
  • Server:HTTP 服务器
  • Handler:HTTP 请求处理程序

最简单的使用

http 包提供了对应于每个 HTTP 动词的函数来发送 HTTP 请求,当不需要对请求进行详细定制时,可以直接使用它们。例如:

resp, err := http.Get("http://example.com/") // GET 请求

resp, err := http.Post("http://example.com/", "application/json", body) // POST 请求

resp, err := http.PostForm("http://example.com/", url.Values{"foo": "bar"}) // 提交表单

HTTP 请求和响应

HTTP 作为通信协议,通过报文传递信息。报文分为请求报文和响应报文,在 http 包中,分别用 RequestResponse 对象进行抽象。

Request

可以通过 NewRequest 创建一个 Request 对象,方法声明如下,需要传入 HTTP 方法、URL 以及报文体进行初始化:

func NewRequest(method, url string, body io.Reader) (*Request, error)

Request 对象主要用于存储请求数据,其结构如下:

type Request struct {
    Method string         // HTTP 方法
    URL    *url.URL       // URL
    Header Header         // 报文头
    Body   io.ReadCloser  // 报文体
    Host   string         // 主机名
    // 其他字段...
}

可以看到 Request 对象可以对请求报文的各个方面进行设置,此外,Request 也提供了一些方法对这些属性进行访问和修改,详细文档可见 Request

Response

Request 对象类似,Response 也是一个数据对象,拥有多个字段来描述 HTTP 响应。需要注意的是 Response 对象引用了当前的 Request 对象。Response 的声明如下:

type Response struct {
    Status        string         // HTTP 状态 "200 OK"
    StatusCode    int            // 状态码 200
    Header        Header         // 响应报文头
    Body          io.ReadCloser  // 响应报文体
    ContentLength int64          // 报文长度
    Request       *Request       // 对应的请求对象
    // 其他字段...
}

Client

在第一节中的 GETPOST 等函数是通过绑定到默认 Client 实现的。你也可以创建自己的 Client 对象。要通过 Client 发出 HTTP 请求,可以先初始化一个 Client 对象,然后发出请求。例如,下面的程序访问 Google:

package main

import (
    "net/http"
    "fmt"
)

func main() {
    client := http.Client{}
    res, err := client.Get("http://www.google.com")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Response Status:", res.Status)
}

对于常用 HTTP 动词,Client 对象提供了对应的函数处理:

func (c *Client) Get(url string) (resp *Response, err error)

func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error)

func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error)

但是在很多情况下,需要对报文头、Cookies 等进行定制,上述方法不能满足需求。因此,Client 对象提供了一个 Do 方法,通过传入一个 Request 对象实现请求的定制化。方法声明如下:

func (c *Client) Do(req *Request) (resp *Response, err error)

下面是一个简单的配置实例:

package main

import (
    "net/http"
    "fmt"
    "io/ioutil"
)

func main() {
    req, err := http.NewRequest(http.MethodGet, "http://www.baidu.com", nil)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    req.Header.Set("Cookie", "name=foo")
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    client := http.Client{}
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(string(body))
}

Server

http 包不仅可以发送 HTTP 请求,还可以创建 HTTP 服务器,对外提供访问服务。可以通过 ListenAndServe 方法创建一个 HTTP 服务:

package main

import (
    "net/http"
    "io"
    "log"
)

func EchoServer(w http.ResponseWriter, req *http.Request) {
    body, err := io.ReadAll(req.Body)
    if err != nil {
        http.Error(w, "Unable to read body", http.StatusBadRequest)
        return
    }
    w.Write(body)
}

func main() {
    http.HandleFunc("/echo/", EchoServer)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

在 Server 模块中,有两个重要的概念:URLHandler。前者是访问的路径,后者是对应的处理函数。Server 需要完成从 URLHandler 的映射。在 http 包中的默认实现是 DefaultServeMux,每个 Handler 需要通过 HandleFunc 进行注册。

HTTP 方法和状态码

除了上述内容外,http 包还定义了一系列常量用于表示 HTTP 动词和返回状态码,详情可见 constants


这个版本对原内容进行了结构优化,并删除了不必要的细节,使其更加简洁易读。

复制全文 生成海报 Go语言 网络编程 HTTP协议

推荐文章

Python实现Zip文件的暴力破解
2024-11-19 03:48:35 +0800 CST
Rust 并发执行异步操作
2024-11-18 13:32:18 +0800 CST
Nginx 性能优化有这篇就够了!
2024-11-19 01:57:41 +0800 CST
Elasticsearch 条件查询
2024-11-19 06:50:24 +0800 CST
LangChain快速上手
2025-03-09 22:30:10 +0800 CST
如何开发易支付插件功能
2024-11-19 08:36:25 +0800 CST
Go语言SQL操作实战
2024-11-18 19:30:51 +0800 CST
vue打包后如何进行调试错误
2024-11-17 18:20:37 +0800 CST
Go中使用依赖注入的实用技巧
2024-11-19 00:24:20 +0800 CST
Go 1.23 中的新包:unique
2024-11-18 12:32:57 +0800 CST
Python中何时应该使用异常处理
2024-11-19 01:16:28 +0800 CST
初学者的 Rust Web 开发指南
2024-11-18 10:51:35 +0800 CST
使用Python提取图片中的GPS信息
2024-11-18 13:46:22 +0800 CST
Vue3中的响应式原理是什么?
2024-11-19 09:43:12 +0800 CST
html折叠登陆表单
2024-11-18 19:51:14 +0800 CST
robots.txt 的写法及用法
2024-11-19 01:44:21 +0800 CST
PHP 唯一卡号生成
2024-11-18 21:24:12 +0800 CST
CentOS 镜像源配置
2024-11-18 11:28:06 +0800 CST
html一份退出酒场的告知书
2024-11-18 18:14:45 +0800 CST
10个几乎无人使用的罕见HTML标签
2024-11-18 21:44:46 +0800 CST
程序员茄子在线接单