云原生系列Go语言篇-标准库 Part 2

net/http

每种编程语言都自带标准库,但随着时间的推移对标准库包含内容的预期在发生变化。作为一个21世纪10年代发布的语言,Go标准库中包含了一些其它语言认为应由第三方库负责的部分:生产级的HTTP/2客户端和服务端。

客户端

​net/http​​包定义了一个​​Client​​类型,发送HTTP请求及接收HTTP响应。​​net/http​​包中有一个默认客户端实例(恰到好处地命名为​​DefaultClient​​),但应当避免在生产应用中使用它,因为它默认不带超时。请实例化自己的客户端。在整个应用中只需要创建一个​​http.Client​​,因为它处理好了跨协程的多并发请求:

client := &http.Client{
    Timeout: 30 * time.Second,
}

在希望发送请求时,通过​​http.NewRequestWithContext​​函数实例化一个新的​​*http.Request​​实例,将上下文、方法和希望连接的URL发送给它。如果为​​PUT​​、​​POST​​或​​PATCH​​请求,最后一个参数使用​​io.Reader​​类型指定请求体。如果没有请求体,使用​​nil​​:

req, err := http.NewRequestWithContext(context.Background(),
    http.MethodGet, "https://jsonplaceholder.typicode.com/todos/1", nil)
if err != nil {
    panic(err)
}

注:我们会在​​上下文​​一章中讨论上下文。

有了​​*http.Request​​实例,就可通过实例的​​Headers​​字段设置请求头。用​​http.Request​​对​​http.Client​​调用​​Do​​方法,结果在​​http.Response​​中返回。

req.Header.Add("X-My-Client", "Learning Go")
res, err := client.Do(req)
if err != nil {
    panic(err)
}

响应中有多个包含请求相应信息的字段。响应状态的数字码位于​​StatusCode​​字段,响应码的文本位于​​Status​​字段,响应头位于​​Header​​字段,返回的内容都位于​​io.ReadCloser​​类型的​​Body​​字段中。这样我们就可以使用​​json.Decoder​​来处理REST API响应了:

defer res.Body.Close()
if res.StatusCode != http.StatusOK {
    panic(fmt.Sprintf("unexpected status: got %v", res.Status))
}
fmt.Println(res.Header.Get("Content-Type"))
var data struct {
    UserID    int    `json:"userId"`
    ID        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
    panic(err)
}
fmt.Printf("%+v\n", data)

可在​​GitHub仓库​​的sample_code/client目录中查看代码。

警告:​​net/http​​包中有方法处理​​GET​​、​​HEAD​​和​​POST​​调用。避免使用这些函数,因为它们使用默认客户端,因此没有设置请求超时。

服务端

HTTP服务端是以​​http.Server​​的概念和​​http.Handler​​接口进行构建的。就像​​http.Client​​是发送HTTP请求的,​​http.Server​​负责监听HTTP的请求。它是一个支持TLS的高性能HTTP/2服务端。

对服务端的请求由赋值给​​Handler​​字段的​​http.Handler​​接口实现来处理。接口中定义了一个方法:

type Handler interface {
    ServeHTTP(http.ResponseWriter, *http.Request)
}

​*http.Request​​很眼熟,它和向HTTP服务端发送请求使用的同一种类型。​​http.ResponseWriter​​是一个带有三个方法的接口:

type ResponseWriter interface {
        Header() http.Header
        Write([]byte) (int, error)
        WriteHeader(statusCode int)
}

这些方法必须按指定顺序调用。首先,调用​​Header​​来获取一个​​http.Header​​实例并设置所需响应头。如果无需设置头部,就不用调用它。接着, 使用响应的HTTP状态码调用​​WriteHeader​​。(所有的状态码在​​net/http​​包中以常量进行定义。这会是定义自定义类型的好地方,但并不完全,所有的状态码常量都是无类型整数。)如果想要发送状态码为200的响应,可以跳过​​WriteHeader​​。最后,调用​​Write​​方法来设置响应体。以下是小型handler的示例:

type HelloHandler struct{}

func (hh HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值