golang的net/http包练习笔记

@[TOC]golang的net/http包练习笔记

简介

正在学习golang,这段时间研究了一下net/http包的使用,主要是client端的request发包,包括使用get/post/postform/do等方法,在此做一记录

package main

import (
	"compress/gzip"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

// var requestGetURLNoParams = "https://www.baidu.com"
var requestGetURLNoParams = "https://www.sohu.com"

// var requestGetURLWithParams = "https://https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=monline_3_dg&wd=golang&fenlei=256&rsv_pq=0xfbdf6e810002e2fb&rsv_t=3cefAeXxNLf2ZS4%2FusXt41oP39aSEZ793S%2Fr%2FaNLReLNoNshrzHk1yC1mVfx&rqlang=en&rsv_dl=tb&rsv_enter=1&rsv_sug3=8&rsv_sug1=2&rsv_sug7=101&rsv_sug2=0&rsv_btype=t&inputT=920&rsv_sug4=1517"

// 基本get请求
func basicGet() {
	resp, err := http.Get(requestGetURLNoParams)
	if err != nil {
		log.Println("err")
	}
	defer resp.Body.Close()
	//在 Go 中 Http 请求的返回结果为 *http.Response 类型,Response.Body 类型为 io.Reader
	//Response 结构体如下
	/*
	   	type Response struct {
	   	Status     string // e.g. "200 OK"
	   	StatusCode int    // e.g. 200
	   	Proto      string // e.g. "HTTP/1.0"
	   	ProtoMajor int    // e.g. 1
	   	ProtoMinor int    // e.g. 0

	   	// Header将头键映射到值。
	   	//如果响应有多个具有相同密钥的头,则可以使用逗号限制将它们串联起来。
	   	//当此结构中的其他字段(如ContentLength、transferncode、Trailer)复制头值时,字段值是权威的。
	   	Header Header

	   	// Body代表响应体。
	   	//响应主体在读取主体字段时按需流式传输。
	   	//如果网络连接失败或服务器终止响应,Body.Read调用返回错误,http客户机和传输保证Body始终为非nil, 关闭响应体时调用者的责任
	   	// 如果响应体未读到完成并关闭,则默认HTTP客户端的传输可能不会重用HTTP/1.x“keep alive”TCP连接
	   	// 如果服务器用“chunked”传输编码答复,则响应体将自动取消dechunked
	   	Body io.ReadCloser

	   	// ContentLength记录关联内容的长度。值>=0表示可以从Body读取给定的字节数。
	   	ContentLength int64

	   	// 包含从最外层到最内层的传输编码。值为nil,表示使用“identity”编码。
	   	TransferEncoding []string

	   	//Close记录响应头是否指示在读取Body之后关闭连接(是为客户提供建议)
	   	Close bool

	   	// 报告响应是否已压缩发送,但已由http包解压缩
	   	// 如果为true,则从Body读取生成未压缩的内容,而不是从服务器实际设置的压缩内容,ContentLength设置为-1,并且从responseHeader中删除“content Length”和“content Encoding”字段
	   	// 一般是压缩方式,利用gzip压缩文档能够显著地减少HTML文档的下载时间。
	   	Uncompressed bool

	   	// 将Trailer 键映射到与标头相同格式的值,初始是nil,服务器的Trailer头值中,指定的每个键对应一个值
	   	Trailer Header

	   	// Request 请求是为获取此响应而发送的请求。请求的主体为零(已被消耗)这仅为客户端请求填充
	   	Request *Request

	   	// TLS包含有关接收响应的TLS连接的信息
	   	TLS *tls.ConnectionState
	   }
	*/
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("err")
	}
	fmt.Println(string(body))
}

// get请求参数放到 "net/url"
func basicGetURLParams() {
	//调用net/url包
	params := url.Values{}
	//将url解析为一个结构体
	parseURL, err := url.Parse(requestGetURLNoParams)
	if err != nil {
		log.Println("err")
	}
	params.Set("aaa", "aaa")
	params.Set("age", "23")
	//如果参数中有中文参数,这个方法会进行URLEncode
	parseURL.RawQuery = params.Encode()
	urlPathWithParams := parseURL.String()
	resp, err := http.Get(urlPathWithParams)
	if err != nil {
		log.Println("err")
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("err")
	}
	fmt.Println(string(b))
}

func httpGetDo() {
	//先生成http.client -> 再生成 http.request -> 之后提交请求:client.Do(request) -> 处理返回结果,每一步的过程都可以设置一些具体的参数
	// 简式声明一个http.Client空结构体指针对象
	client := &http.Client{}

	// 使用http.NewRequest构建http Request请求
	//func NewRequest(method, url string, body io.Reader) (*Request, error)
	request, err := http.NewRequest("GET", requestGetURLNoParams, nil)
	if err != nil {
		log.Println("err")
	}

	// 使用http.Cookie结构体初始化一个cookie键值对
	cookie := &http.Cookie{Name: "userId", Value: strconv.Itoa(12345)}

	/*
			 // 另一种添加cookie的方法
		 	cookie := &http.Cookie{
		 		Name: "aaa",
		 		Value: "aaa-value",
		 	}
		 	req.AddCookie(cookie1)



	*/

	// 使用前面构建的request方法AddCookie往请求中添加cookie
	request.AddCookie(cookie)

	// 设置request的Header,具体可参考http协议
	request.Header.Set("Accept", "text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8")
	request.Header.Set("Accept-Charset", "GBK, utf-8;q=0.7, *;q=0.3")
	request.Header.Set("Accept-Encoding", "gzip, deflate, sdch")
	request.Header.Set("Accept-Language", "zh-CN, zh;q=0.8")
	request.Header.Set("Cache-Control", "max-age=0")
	request.Header.Set("Connection", "keep-alive")

	// 使用http.Client 来发送request,这里使用了Do方法。
	response, err := client.Do(request)
	if err != nil {
		log.Println(err)
		return
	}

	// 程序结束时关闭response.Body响应流
	defer response.Body.Close()

	// 接收到的http Response 状态值
	fmt.Println(response.StatusCode)
	if response.StatusCode == 200 { // 200意味成功得到http Server返回的http Response信息

		// gzip.NewReader对压缩的返回信息解压(考虑网络传输量,http Server
		// 一般都会对响应压缩后再返回)
		body, err := gzip.NewReader(response.Body)
		// body := response.Body
		if err != nil {
			log.Println(err)
		}

		defer body.Close()

		r, err := ioutil.ReadAll(body)
		if err != nil {
			log.Println(err)
		}
		// 打印出http Server返回的http Response信息
		log.Println(string(r))
	}

}

func basicPost() {
	//func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error)

	/*
			func NewReader(s string) *Reader {
		    return &Reader{s, 0, -1}
		     }
	*/
	/*
			type Reader interface {
		    Read(p []byte) (n int, err error)
			}
	*/
	resp, err := http.Post("http://localhost:8080/login.do",
		"application/x-www-form-urlencoded", strings.NewReader("mobile=xxxxxxxxxx&isRemberPwd=1"))
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return
	}
	fmt.Println(string(body))
}

func basicPostForm() {
	//func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error)
	//PostForm向指定的URL发出一个POST请求,url.Values类型的data会被编码为请求的主体。
	//POST数据的类型一般会设为"application/x-www-form-urlencoded"
	postParam := url.Values{
		"mobile":      {"xxxxxx"},
		"isRemberPwd": {"1"},
	}
	// 数据的键值会经过URL编码后作为请求的body传递
	resp, err := http.PostForm("http://localhost:8080/login.do", postParam)
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return
	}
	fmt.Println(string(body))
}

func main() {
	//Get方法
	basicGet()

	//get with params
	basicGetURLParams()
	//Post方法
	basicPost()

	//Postform方法
	basicPostForm()
	//http.do
	httpGetDo()

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值