Golang提供了官方的http包,對於http操作非常的方便和簡潔。
但是不同於PHP,使用Golang的包來做http操作,還是沒有那么”直接“,需要實例化一下這個,實例化一下那個,有點像Java
,因此,為了以后書寫方便,就把基本的請求寫在此。下次用的時候,直接copy就好了。
get 請求
get請求有好幾種方式
直接使用net/http
包內的函數請求
import "net/http" ... resp, err := http.Get("http://wwww.baidu.com")
利用http.client結構體來請求
import "net/http" ... clt := http.Client{} resp, err := clt.Get("http://wwww.baidu.com")
最本質的請求方式
如果稍微看一下源碼,就會發現以上兩種方式都是用了一下這種最本質的請求方式,
使用http.NewRequest
函數
req, err := http.NewRequest("GET", "http://www.baidu.com", nil) //然后http.client 結構體的 Do 方法 //http.DefaultClient可以換為另外一個http.client resp, err := http.DefaultClient.Do(req)
Go的get請求面上有好幾種請求方式,實則只有一種:
1、使用http.NewRequest
函數獲得request
實體。
2、利用http.client
結構體的Do
方法,將request
實體傳入Do
方法中。
post請求
和get請求類似,post請求也有多種方法,但本質還是使用了http.NewRequest
函數和http.client
的Do
方法。
使用net/http
包帶的post方法
import ( "net/http" "net/url" ) ... data := url.Values{"start":{"0"}, "offset":{"xxxx"}} body := strings.NewReader(data.Encode()) resp, err := http.Post("xxxxxxx", "application/x-www-form-urlencoded", body)
或者還可以
import ( "net/http" "net/url" ) ... var r http.Request r.ParseForm() r.Form.Add("xxx", "xxx") body := strings.NewReader(r.Form.Encode()) http.Post("xxxx", "application/x-www-form-urlencoded", body)
要是還是覺得復雜,還可以:
import ( "net/http" "net/url" ) ... data := url.Values{"start":{"0"}, "offset":{"xxxx"}} http.PostForm("xxxx", data)
使用實例化的http client的post方法
其實本質上直接使用包的函數和實例化的http client是一樣的,包的函數底層也僅僅是實例化了一個DefaultClient
,然后調用的DefaultClient
的方法。
下面給出使用實例化的http client的post方法:
import ( "net/http" "net/url" ) ... data := url.Values{"start":{"0"}, "offset":{"xxxx"}} body := strings.NewReader(data.Encode()) clt := http.Client{} resp, err := clt.Post("xxxxxxx", "application/x-www-form-urlencoded", body)
還有
import ( "net/http" "net/url" ) ... var r http.Request r.ParseForm() r.Form.Add("xxx", "xxx") body := strings.NewReader(r.Form.Encode()) clt := http.Client{} clt.Post("xxxx", "application/x-www-form-urlencoded", body)
簡單的,但僅限於form表單
import ( "net/http" "net/url" ) ... data := url.Values{"start":{"0"}, "offset":{"xxxx"}} clt := http.Client{} clt.PostForm("xxxx", data)
使用net/http
包的NewRequest
函數
其實不管是get方法也好,post方法也好,所有的get、post的的http 請求形式,最終都是會調用net/http
包的NewRequest
函數,多種多樣的請求形式,也僅僅是封裝的不同而已。
import ( "net/http" "net/url" ) ... data := url.Values{"start":{"0"}, "offset":{"xxxx"}} body := strings.NewReader(data.Encode()) req, err := http.NewRequest("POST", "xxxxx", body) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") clt := http.Client{} clt.Do(req)
添加request header
net/http
包沒有封裝直接使用請求帶header的get或者post方法,所以,要想請求中帶header,只能使用NewRequest
方法。
import ( "net/http" ) ... req, err := http.NewRequest("POST", "xxxxx", body) //此處還可以寫req.Header.Set("User-Agent", "myClient") req.Header.Add("User-Agent", "myClient") clt := http.Client{} clt.Do(req)
有一點需要注意:在添加header操作的時候,req.Header.Add
和req.Header.Set
都可以,但是在修改操作的時候,只能使用req.Header.Set
。
這倆方法是有區別的,Golang底層Header的實現是一個map[string][]string
,req.Header.Set
方法如果原來Header中沒有值,那么是沒問題的,如果又值,會將原來的值替換掉。而req.Header.Add
的話,是在原來值的基礎上,再append
一個值,例如,原來header的值是“s”,我后req.Header.Add
一個”a”的話,變成了[s a]
。但是,獲取header值的方法req.Header.Get
確只取第一個,所以,如果原來有值,重新req.Header.Add
一個新值的話,req.Header.Get
得到的值不變。
打印response響應
Golang打印response沒有PHP那么爽,哎,編譯型語言就是麻煩。
import ( "net/http" "net/url" "io/ioutil" ) ... content, err := ioutil.ReadAll(resp.Body) respBody := string(content)
使用cookie
Golang提供了cookie的包net/http/cookiejar
... url, err := url.Parse("https://www.wukong.com/") jar, err := cookiejar.New(nil) jar.SetCookies(url, cookies)//這里的cookies是[]*http.Cookie wukongClt := http.Client{Transport:nil, Jar:jar} wukongClt.Get("xxxxx")
Golang的cookie是和http.client
聯系在一起的,作為http.client
的一個屬性存在。因此,要想在Golang中使用cookie,就必須想辦法構造http.client
文中的cookies
類型是[] *http.cookie
可以自己實例化,有時候也可以從response
中直接使用resp.Cookies()
直接拿到。
使用代理
在Golang中使用http proxy,也必須構造自己的http.client
,需要將http.client
結構體的一個屬性Transport
自己實例化好。
當使用環境變量$http_proxy或$HTTP_PROXY作為代理時
//從環境變量$http_proxy或$HTTP_PROXY中獲取HTTP代理地址 func GetTransportFromEnvironment() (transport *http.Transport) { transport = &http.Transport{Proxy : http.ProxyFromEnvironment} return }
參數proxy_addr
即代理服務器IP端口號,例如:”http://xxx.xxx.xxx.xxx:6000“,注意,必須加上"http"當使用自己搭建http代理時
func GetTransportFieldURL(proxy_addr *string) (transport *http.Transport) { url_i := url.URL{} url_proxy, error := url_i.Parse(*proxy_addr) if error != nil{ fmt.Println(error.Error()) } transport = &http.Transport{Proxy : http.ProxyURL(url_proxy)} return }
使用的時候,首先調用函數,拿到對應的transport
,即使用GetTransportFieldURL
或者GetTransportFieldURL
函數,然后構建自定義的http.client
:
ProxyUrl := "http://xxx.xxx.xxx.xxx:6000" transport := GetTransportFieldURL(&ProxyUrl) clt := http.Client{Transport:transport} clt.Get("http://www.baidu.com")