Go语言基础(7)——http网络编程

50 阅读2分钟

http网络编程

客户端http

http包中提供了一个Client的struct

type Client struct {
    Transport RoundTripper
    CheckRedirect func(req *Request, via []*Request) error
    Jar CookieJar
    Timeout time.Duration
}

其提供的函数也比较少,只有Do、Get、Post、PostForm以及Head,后面四个函数都是用Do函数来实现的。其中Get是发起一个Get请求,Post和PostForm函数表示发送一个Post请求,Head表示发送一个Head请求,而Do表示发送一个任意method请求。Do函数的签名为 func (c *Client) Do(req *Request) (*Response, error) 是个非常典型的同步调用函数,传入一个req返回一个resp。

Request类型无非就包括那么些http的请求参数,比如method类型(GET/POST/HEAD等),url、header等,将这些参数传给Request就能构造出一个发起http请求的Request。

Response的函数和参数也不多,也只有一些基本的http响应的参数。主要包括:

  • 响应码:StatusCode
  • 响应说明:Status
  • 响应头:Header
  • ContentLength:响应长度
  • Body:最重要的服务器返回的内容
func Request() {
   resp, err := http.DefaultClient.Get("https://www.baidu.com")
   if err != nil {
      panic(err)
   }
   fmt.Println(resp.StatusCode, resp.Status, resp.Header, resp.ContentLength)
   body, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      panic(err)
   }
   fmt.Println(string(body))
}

上面的代码是使用http发送一个Get请求,访问baidu首页

服务端http

go的http服务端也是在http包中,go sdk提供了一套http server的实现。

func Server() {
   err := http.ListenAndServe(":8080", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
      writer.WriteHeader(http.StatusOK)
      _, _ = writer.Write([]byte(fmt.Sprintf("hello %s\n", request.URL.Path)))
   }))
   if err != nil {
      panic(err)
   }
}

上面的代码用http包实现了一个最简单的http server,监听8080端口,对所有的请求都返回200,并返回body为hello + 请求的path

查看http.ListenAndServe的源码不难发现,其是创建了一个http.Server,然后调用server#ListenAndServe函数。其中http.Server的创建需要传入一个addr和一个Handler,这个Handler就是我们传入的http.HandleFunc函数,这表明这个Server只能有一个处理函数,那么如果我们需要为每个path添加一个Handler呢?

这时就需要使用http包提供的ServeMux,其Handle函数签名为Handle(pattern string, handler Handler),pattern表示path的正则,handler就是path的处理函数。

https的支持

现在的http服务器,基本上都被要求使用https协议来保证数据传输的安全,go的http包当然也提供了对https协议的支持。还是以一个最简单的https server举例:

func HttpsServer() {
   fmt.Println(os.Executable())
   err := http.ListenAndServeTLS(":8080", "./conf/server.crt", "./conf/server.key", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
      writer.WriteHeader(http.StatusOK)
      _, _ = writer.Write([]byte(fmt.Sprintf("hello %s\n", request.URL.Path)))
   }))
   if err != nil {
      panic(err)
   }
}