golang http客户端实例

golang的net/http包已经提供了强大了网络操作函数,我们编写的web客户端示例如下:

package main

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

func main() {
  //Get请求
    res, err := http.Get("http://www.baidu.com")
    if err != nil {
        log.Fatal(err)
    }
  //利用ioutil包读取百度服务器返回的数据
    data, err := ioutil.ReadAll(res.Body)
    res.Body.Close()//一定要记得关闭连接
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("%s", data)
}

可以通过请求头来控制请求的参数。

设置请求头参数之前需求构造一个请求,从而进行参数设定。我们首先将main函数改造成如下所示:

func main() {
    client := &http.Client{}
    url := "http://www.baidu.com"
    req, err := http.NewRequest("GET", url, nil)//GET大写
    if err != nil {
        log.Fatal(err)
    }
    rep, err := client.Do(req)//发起请求
    if err != nil {
        log.Fatal(err)
    }
    data, err := ioutil.ReadAll(rep.Body)
    rep.Body.Close()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("%s", data)
}

客户端在发送请求时,可以通过设定请求头中的多项参数规范请求的特性,例如字符编码集、语言等等,详细信息大家可以参照:这里 

常见的几项设置:

Accept::浏览器可接受的数据类型;
Accept-Charset:浏览器可接受的字符编码集;
Accept-Encoding:浏览器可接受的编码方法;
Accept-Language:浏览器可接受的语言;
Connection:是否为持久连接,默认长连接keep-alive,由于网页数据很多,所以浏览器可能是连续多次请求服务器数据的,此时多次访问只有首次完成tcp3次握手,减少消耗;而tcp中的keep-alive是tcp连接的有效时长,一般比http的keep-alive的时间长。
Cookie:Cookie值;
Content-Lenght:请求内容的长度,过长和果断将导致请求内容截断;如果不知道可以不设置,交由底层完成;
Host:访问的服务器地址;
User-Agent:用户信息。

了解基本几个参数的设置后,将其设置为相应的值即可,执行后即可拿到百度服务器返回的数据。

func main() {
    client := &http.Client{}
    url := "http://www.baidu.com"
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatal(err)
    }

    req.Header.Add("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
    req.Header.Add("Accept-Charset","utf-8")
    //req.Header.Add("Accept-Encoding","br, gzip, deflate")
    req.Header.Add("Accept-Language","zh-cn")
    req.Header.Add("Connection","keep-alive")
    //req.Header.Add("Cookie","xxxxxxxxxxxxxxx")
    //req.Header.Add("Content-Lenght",xxx)
    req.Header.Add("Host","www.baidu.com")
    req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")
    rep, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    data, err := ioutil.ReadAll(rep.Body)
    rep.Body.Close()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("%s", data)
}

百度作为一个搜索平台,我们可以在请求中加入搜索词,然后获取搜索结果。还有很多场景都需要我们提交数据,如注册登陆、Google翻译等等。那如何提交数据呢?这就要用post方法向服务器提交。

func main() {
    client := &http.Client{}
    req_data := `{"name":"ali", "age":"18"}`
    url := "http://www.baidu.com"
    req, err := http.NewRequest("POST", url,  strings.NewReader(req_data))
    if err != nil {
        log.Fatal(err)
    }
    //Content-Type很重要,下文解释
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    //req.Header.Set("Content-Type", "application/json")
    //req.Header.Set("Content-Type", "multipart/form-data")

    rep, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    data, err := ioutil.ReadAll(rep.Body)
    rep.Body.Close()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("%s", data)
}

上面的代码意在向百度提交name和age数据,由于百度服务器并不识别name和age,所以无法返回正确的数据,但流程上是正确的。其中有必要说一下Content-Type,它是用于规定提交数据的类型,常见的有application/x-www-form-urlencoded、application/form-data和application/json等,下面分别说明一下:

application/x-www-form-urlencoded:最常见的类型之一,表示将数据转化为键值对后提交,例如name=ali&age=18.但是如果有本身数据中有&字符就可能造成歧义,例如二进制文件等。

application/form-data:表示以表格数据上报,即将多组数据以一串复杂的boundary数据分隔,而非&符;因此这种数据类型可以用于上传文件或有&符的数据。

application/json:表示将提交的数据转化成json格式。

更多有关content-type的资料请参照这里

结合之前文章中提到的gorutine,sync.WaitGroup等知识,将代码简化封装成如下所示。可以通过修改url的值访问本地服务器。

package main

import (
	"io/ioutil"
	"log"
	"net/http"
	"sync"
)

var wc sync.WaitGroup

func HelloClient(client *http.Client, url string){
	defer wc.Done()
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	rep, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	data, err := ioutil.ReadAll(rep.Body)
	rep.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%s", data)
}
func main() {
	client := &http.Client{}
	url := "http://127.0.0.1:8000"
	wc.Add(10)
	for i := 0; i < 10; i++{
		go HelloClient(client, url)
	}
	wc.Wait()
}

 原文地址:https://zhuanlan.zhihu.com/p/134146738

上一篇:算法:相同的树


下一篇:智能指针weak_ptr记录