1. 前言

标准库是工具,是手段,是拿来用的。一味的学标准库就忽视了语言的内核,关键。语言层面的特性,内存管理,垃圾回收。数据结构,设计模式。这些是程序的内核,要熟练,乃至精通它们,而不是精通标准库。

标准库是需要掌握的,了解的。可以通过标准库深挖语言的特性,但不能只学标准库,学所谓的表面的东西。

基于这个目的,这里不会深入介绍 http 标准库,因为它内容太广,想深亦难。当然不是说不要,是要的,部分内容留作后续研究。

2. net/http 介绍

http 是超文本传输协议,是基于 TCP/IP 协议之上的应用层协议。HTTP 协议入门 清晰的介绍了 HTTP 协议。

Go 中实现 http 协议的包是 net/http。实现 http 协议需要 HTTP request 请求和 HTTP response 响应,请求和响应分别对应 Request 和 Response 结构体,如下:

type Request struct {
Method string URL *url.URL Proto string // "HTTP/1.0"
ProtoMajor int // 1
ProtoMinor int // 0 Header Header
...
} type Response struct {
Status string // e.g. "200 OK"
StatusCode int // e.g. 200
Proto string // e.g. "HTTP/1.0"
ProtoMajor int // e.g. 1
ProtoMinor int // e.g. 0 Header Header
Body io.ReadCloser
...
}

抓住了结构体就抓住了实例对应的属性和方法。

这里构造 server 端实现 http response 响应:

package main

import (
"io"
"log"
"net/http"
) func main() {
helloHandler := func(w http.ResponseWriter, req *http.Request) {
sr := "hello, world with request " + req.Method
io.WriteString(w, sr)
} http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":8082", nil))
}

其中:

  • ListenAndServe 调用 net 包的 Listen 方法实现 tcp 地址 (ip + port) 的侦听,Go 标准库 net 介绍了 net 包相关内容。

  • http.ResponseWriter 是接口,它实现了 Header,Write,WriteHeader 方法向响应添加 header 和 body 内容。如定义当调用 /hello api 时返回 404 状态码,可调用 WriterHeader 方法如下:

    w.WriteHeader(404)
    sr := "hello, world with request " + req.Method
    io.WriteString(w, sr)

    注意状态码不能重复写,如将 WriteHeader(404) 置于 WriteString 后会报错 http: superfluous response.WriteHeader call from

  • http.Request 是客户端发来的请求,在 Handler 中可使用该请求组合生成响应信息。这里将返回字符和请求方法结合作为响应发给客户端。

继续构造客户端实现 HTTP request 请求:

func main() {
response, err := http.Get("http://127.0.0.1:8082/hello")
if err != nil {
fmt.Println(err)
os.Exit(1)
} defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(body))
fmt.Println(response)
fmt.Println(*response.Request)
}

运行 server 和 client:

// run server
[chunqiu@test http]$ go run server/server.go // run client
[chunqiu@test http]$ go run main.go
hello, world with request GET &{404 Not Found 404 HTTP/1.1 1 1 map[Content-Length:[29] Content-Type:[text/plain; charset=utf-8] Date:[Mon, 06 Dec 2021 02:18:11 GMT]] 0xc00009c040 29 [] false false map[] 0xc000140000 <nil>} {GET http://127.0.0.1:8082/hello HTTP/1.1 1 1 map[] <nil> <nil> 0 [] false 127.0.0.1:8082 map[] map[] <nil> map[] <nil> <nil> <nil> 0xc0000160a0}

从打印返回值可以看到:

  • server response 为前面写入的状态码 404;server 和 client 通信使用的 HTTP 协议为 HTTP/1.1;response 的 Header 头信息包括 Content-Length,Content-Type 和 Date 信息,其中 Content-Length 表示文本,或其它类型的“长度”,如对于 zip 类型,返回的 Content-Length 是 zip 的大小:Length: 3116622545 (2.9G) [application/zip]
  • server 的 response 也包括了 request 的信息,request 是 response 的属性,可通过 response.Request 调用 Request 信息。

不仅是返回值头信息,在 Request 也可以定义头信息,如 Content-Type 定义接收类型,Accept 定义接收数据格式等。

3. 程序示例

看一段代码:

req, err := http.NewRequest(method, url, data)
if err != nil {
return nil, false, err
} req.Header.Add("Content-Type", "application/json; charset=utf-8")
resp, err := client.Do(req)
if err != nil {
return nil, false, err
}
defer resp.Body.Close()
out, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, false, err
}

这里使用了 NewRequest 函数创建 req 实例,通过 client 调用 req 的 url 和相应的方法,并且在 req 的头信息添加 Content-Type 声明请求的 body 信息。有一点需要注意的是 ioutil 包的 ReadAll 方法,它的函数原型为:

// ReadAll reads from r until an error or EOF and returns the data it read.
// A successful call returns err == nil, not err == EOF. Because ReadAll is
// defined to read from src until EOF, it does not treat an EOF from Read
// as an error to be reported.
//
// As of Go 1.16, this function simply calls io.ReadAll.
func ReadAll(r io.Reader) ([]byte, error)

相关的描述信息见源代码注释。其中 ReadAll 函数参数为 io.Reader,它是一个实现了 Read 方法的接口。而 resp.Body 是 io.ReadCloser 接口的实例,io.ReadCloser 实现了 Reader 和 Closer 方法。看到了吗,这里发生了接口的赋值,关于接口设计与实现及接口赋值部分留作后续研究。

还有一部分内容有待后续研究的是:http 是基于 TCP/IP 之上的应用层协议,它的实现不需要关心底层 TCP/IP 的实现,这是好处又是不好的地方,底层做了什么, TCP/IP 怎么处理 http 包,从 client 到 server 经过了什么,具体流程是什么样的。这部分是不明确的,如果不掌握这部分内容 http 传输出现问题很难 debug。


小白学标准库之 http的更多相关文章

  1. 小白学 Python 爬虫(21):解析库 Beautiful Soup(上)

    小白学 Python 爬虫(21):解析库 Beautiful Soup(上) 人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前 ...

  2. 小白学 Python 爬虫(22):解析库 Beautiful Soup(下)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  3. 小白学 Python 爬虫(23):解析库 pyquery 入门

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  4. 小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  5. 什么是 C 和 C ++ 标准库?学编程的你应该知道这些知识!

    简要介绍编写C/C ++应用程序的领域,标准库的作用以及它是如何在各种操作系统中实现的. 我已经接触C++一段时间了,一开始就让我感到疑惑的是其内部结构:我所使用的内核函数和类从何而来? 谁发明了它们 ...

  6. 【循序渐进学Python】11.常用标准库

    安装完Python之后,我们也同时获得了强大的Python标准库,通过使用这些标准库可以为我们节省大量的时间.这里是一些常用标准库的简单说明.更多的标准库的说明,可以参考Python文档 sys 模块 ...

  7. 小白学 Python 爬虫(18):Requests 进阶操作

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  8. 小白学 Python 爬虫(25):爬取股票信息

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  9. 小白学Java:I/O流

    目录 小白学Java:I/O流 基本分类 发展史 文件字符流 输出的基本结构 流中的异常处理 异常处理新方式 读取的基本结构 运用输入与输出 文件字节流 缓冲流 字符缓冲流 装饰设计模式 转换流(适配 ...

  10. 小白学 Python 数据分析(11):Pandas (十)数据分组

    人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...

随机推荐

  1. 从滑动窗口到YOLO、Transformer:目标检测的技术革新

    本文全面回顾了目标检测技术的演进历程,从早期的滑动窗口和特征提取方法到深度学习的兴起,再到YOLO系列和Transformer的创新应用.通过对各阶段技术的深入分析,展现了计算机视觉领域的发展趋势和未 ...

  2. keycloak~对接login-status-iframe页面判断用户状态变更

    上次我们说了,keycloak的login-status-iframe页面的作用,并解决了跨域情况下,iframe与主页面数据传递的方法,这一次,我们主要分析login-status-iframe.h ...

  3. SSM整合 tomcat报错: <严重 [RMI TCP Connection(22)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal 一个或多个筛选器启动失败。完整的详细信息将在相应的容器日志文件中找到>

    前提:学了一个暑假 从Javaweb -> mybits ->spring -> spring-mvc 打算跟着网上ssm整合项目做一个项目 在完成最后一步spring对spring ...

  4. 【C++】【图像处理】形态学处理(腐蚀、膨胀)算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)

    1 void erosion(BYTE* image, int w, int h, BYTE* outImg) 2 { 3 int rept; 4 //腐蚀 5 memcpy(outImg, imag ...

  5. uni-app+vue3+ts项目搭建完整流程

    项目代码同步更新至码云 uni-vue3-ts-template 开发前准备 利用 uni-app 开发,有两种方法: 通过 HBuilderX 创建(需安装 HBuilderX 编辑器) 通过命令行 ...

  6. 神经网络优化篇:理解指数加权平均数(Understanding exponentially weighted averages)

    理解指数加权平均数 回忆一下这个计算指数加权平均数的关键方程. \({{v}_{t}}=\beta {{v}_{t-1}}+(1-\beta ){{\theta }_{t}}\) \(\beta=0. ...

  7. KubeCon China 2023 | 拥抱开源,华为云原生华彩绽放

    本文分享自华为云社区<KubeCon China 2023 | 拥抱开源,华为云原生华彩绽放>,作者: 云容器大未来 . 2023 年度云原生全球旗舰盛会 KubeCon + CloudN ...

  8. 跟我读论文丨ACL2021 NER 模块化交互网络用于命名实体识别

    摘要:本文是对ACL2021 NER 模块化交互网络用于命名实体识别这一论文工作进行初步解读. 本文分享自华为云社区<ACL2021 NER | 模块化交互网络用于命名实体识别>,作者: ...

  9. 数仓出现“wait in ccn queue”的时候,怎么迅速定位处理?

    摘要:现网在使用动态负载管理的时候,经常出现很多wait in ccn的情况,大家处理起来就会认为是hung住或者怎么着了,很着急,但wait ccn其实就是一个等待资源的状态,在此总结一个ccn问题 ...

  10. 基于MRS-Hudi构建数据湖的典型应用场景介绍

    摘要:华为云FunsionInsight MRS已集成Apache Hudi 0.8版本,基于MRS-Hudi构建数据湖解决方案. 本文分享自华为云社区<基于MRS-Hudi构建数据湖的典型应用 ...