我们在正式学习Hertz框架之前,先来看看如果我们不用框架的话,要怎么响应信息到互联网。
说到网络编程,我们最基础的就是获取网络上的信息,和返回网络信息对吧。
分别就是发送请求和发送响应。
这就是我们这篇博客所介绍的事情。
首先要导入一个Go语言的网络库:
这个http包提供了HTTP客户端和服务端的实现。
首先是客户端Client:发送请求,获取信息
比如我们可以发送请求:
这样我们可以通过发送请求去获取一些页面信息:
//Get请求
resp, err := http.Get("https://www.baidu.com")
if err != nil {
fmt.Println("err", err)
}
//关闭Body
defer resp.Body.Close()
//读取body内容
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("read from resp.Body failed, err", err)
return
}
//输出字符串内容
fmt.Println(string(body))
我们也可以操作其它客户端行为,比如:
我们先来说说Cilent是什么?
Client
这里顾名思义就是HTTP
客户端,用于发送HTTP
请求(Request
) 并获得响应Respone
。下面我们来详细介绍下在
Go
语言的net/http
包中,Client
是如何被定义以及使用的。
Go语言中的
http.Client
结构体是用于发送HTTP
请求并返回响应的组件。它的定义如下:type Client struct { Transport RoundTripper CheckRedirect func(req *Request, via []*Request) error Jar CookieJar Timeout time.Duration }
Transport
一个
http.RoundTripper
接口类型的对象,只包含一个方法RoundTrip
,它接受一个*http.Request
类型的参数,表示HTTP请求,返回一个*http.Response
类型的响应和一个错误对象,该方法的作用是发送HTTP
请求并返回响应,同时处理可能出现的传输错误,如超时、连接错误、重定向等。
http.RoundTripper
的默认实现是http.Transport
,该实现使用TCP
连接池,支持HTTP/1.1
、HTTP/2
协议,同时还支持HTTPS
、代理、压缩和连接复用等特性。如果需要更灵活地控制HTTP
请求的传输过程,可以自定义实现http.RoundTripper
接口,并将其传递给http.Client
的Transport
字段。
CheckRedirect
一个函数类型,用于控制
HTTP
重定向。默认情况下,http.DefaultCheckRedirect
允许自动跟随HTTP
重定向。
Jar
一个
http.CookieJar
接口类型的对象,用于管理HTTP cookie
。默认情况下,http.DefaultCookieJar
使用net/http/cookiejar
包中的默认cookie
实现。
Timeout
一个
time.Duration
类型的对象,用于控制HTTP
请求的超时时间。默认情况下,如果该字段没有设置超时时间,即无限期等待响应。
我们接下来就可以来创建一个http客户端:
Client := &http.Client{}
当然也可以创建得更加精细:
使用
http.Client
进行发送HTTP
请求以及返回响应,基本流程如下:
- 创建
http.Client
对象。首先,我们需要创建一个http.Client
对象。可以通过http.DefaultClient
使用默认的HTTP客户端,也可以通过手动创建一个新的http.Client
对象,以便自定义其参数。- 创建
HTTP
请求。有了http.Client
对象后,我们需要创建一个HTTP
请求。在Request
章节中,我们讲述到http.NewRequest
函数,我们可以通过该函数创建一个新的请求对象,并设置请求URL
、方法、请求体等参数。- 发送
HTTP
请求。有了请求对象后,将请求对象传递给http.Client
的Do
方法,以便发送HTTP
请求。Do
方法返回一个响应对象,其中包含服务器的响应信息,如状态码、响应头和响应体等。- 处理
HTTP
响应。我们可以使用响应对象中的方法和属性,如resp.StatusCode
、resp.Header
、resp.Body
等,处理服务器的响应。通常,我们需要读取响应体的内容,并将其解析为合适的数据类型,如JSON
或XML
。- 关闭
HTTP
响应。获取响应后,我们需要确保关闭HTTP
响应的主体。可以使用defer resp.Body.Close()
语句在函数退出时自动关闭响应体,以避免内存泄漏。
下面就是一个客户端的小实例:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// 创建http.Client对象
client := &http.Client{}
// 创建HTTP请求
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
panic(err)
}
// 发送HTTP请求
resp, err := client.Do(req)
if err != nil {
panic(err)
}
// 处理HTTP响应
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
如果想要看更多原生使用,可以参考:Go语言标准库之net/http(三) —— Client - xjx的文章 - 知乎 https://zhuanlan.zhihu.com/p/624745481
补充demo:
package main
import (
"fmt"
"net/http"
)
// 处理GET请求
func handleGet(writer http.ResponseWriter, request *http.Request) {
query := request.URL.Query()
id := query.Get("id")
fmt.Printf("GET: id=%s\n", id)
fmt.Fprintf(writer, "GET: id=%s\n", id)
fmt.Fprintf(writer, `{"code":0}`)
}
func main() {
http.HandleFunc("/testGet", handleGet)
http.ListenAndServe(":1111", nil)
}
其次是服务器Server端:发送响应,返回数据
ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量DefaultServeMux作为处理器。Handle和HandleFunc函数可以向DefaultServeMux添加处理器。
举个例子:
package main
import (
"fmt"
"html"
"net/http"
)
func main() {
http.HandleFunc("/ok", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
http.ListenAndServe(":1111", nil)
}
运行效果如图:
大概这样就算是启动了一个http包里默认的服务器,监听了:1111端口,路由是/ok,并且运行了一个(函数)处理器 。
当然也可以自定义服务器做很多精细化的处理: