go:net/http内置库包

143 阅读2分钟

参考网址

www.cnblogs.com/wukai66/p/1…

1/前言

go语言内置的net/http库包是十分优秀的库包,提供了http客户端和服务端的实现。

http,是超文本传输协议,(HTTP,HyperText Transfer Protocol)
是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。

2/http客户端

Get、Head、Post和PostForm这些函数都是可以发出HTTP/HTTPS请求的。
程序在使用完response后必须关闭回复的主体。
response, err := http.Get("http://example.com/")
...
response, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
...
response, err := http.PostForm("http://example.com/form",
    url.Values{"key": {"Value"}, "id": {"123"}})

// 程序在使用完response后必须关闭回复的主体。

resp, err := http.Get("http://example.com/")  // 从服务端获得响应response
if err != nil {
    // handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

<1>Get()函数请求示例

使用`net/http`包编写一个简单的发送HTTP请求的Client端,代码如下:
package main

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

func main() {
  resp, err := http.Get("https://www.liwenzhou.com/")
  if err != nil {
      fmt.Println("get failed, err:", err)
      return
  }
  defer resp.Body.Close() //关闭主体
  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
      fmt.Println("read from resp.Body failed,err:", err)
      return
  }
  fmt.Print(string(body))
}
// 将上面的代码保存之后编译成可执行文件,执行之后就能在终端打印`liwenzhou.com`网站首页的内容了,
// 我们的浏览器其实就是一个发送和接收HTTP协议数据的客户端,
// 我们平时通过浏览器访问网页其实就是从网站的服务器接收HTTP数据,然后浏览器会按照HTML、CSS等规则将网页渲染展示出来。

<2>带参数的GET请求示例

关于GET请求的参数需要使用Go语言内置的`net/url`这个标准库来处理。
func main() {
    apiUrl := "http://127.0.0.1:9090/get"
    // URL param
    data := url.Values{}
    data.Set("name", "小王子")
    data.Set("age", "18")
    u, err := url.ParseRequestURI(apiUrl)
    if err != nil {
        fmt.Printf("parse url requestUrl failed,err:%v\n", err)
    }
    u.RawQuery = data.Encode() // URL encode
    fmt.Println(u.String())
    resp, err := http.Get(u.String())
    if err != nil {
        fmt.Println("post failed, err:%v\n", err)
        return
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("get resp failed,err:%v\n", err)
        return
    }
    fmt.Println(string(b))
}
// 对应的Server端HandlerFunc如下:
func getHandler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    data := r.URL.Query()
    fmt.Println(data.Get("name"))
    fmt.Println(data.Get("age"))
    answer := `{"status": "ok"}`
    w.Write([]byte(answer))
}

<3>Post()请求示例

上面演示了使用net/http库包发送Get()请求的示例,发送Post()的示例代码如下:
package main

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

// net/http post demo

func main() {
   url := "http://127.0.0.1:9090/post"
   // 表单数据
   //contentType := "application/x-www-form-urlencoded"
   //data := "name=小王子&age=18"
   // json
   contentType := "application/json"
   data := `{"name":"小王子","age":18}`
   resp, err := http.Post(url, contentType, strings.NewReader(data))
   if err != nil {
       fmt.Println("post failed, err:%v\n", err)
       return
   }
   defer resp.Body.Close()
   b, err := ioutil.ReadAll(resp.Body)
   if err != nil {
       fmt.Println("get resp failed,err:%v\n", err)
       return
   }
   fmt.Println(string(b))
}

// 对应的Server端HandlerFunc如下:
func postHandler(w http.ResponseWriter, r *http.Request) {
   defer r.Body.Close()
   // 1. 请求类型是application/x-www-form-urlencoded时解析form数据
   r.ParseForm()
   fmt.Println(r.PostForm) // 打印form数据
   fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
   // 2. 请求类型是application/json时从r.Body读取数据
   b, err := ioutil.ReadAll(r.Body)
   if err != nil {
       fmt.Println("read request.Body failed, err:%v\n", err)
       return
   }
   fmt.Println(string(b))
   answer := `{"status": "ok"}`
   w.Write([]byte(answer))
}