目錄
寫在前面
發(fā)送Post請求
示例代碼
源碼分析
Post請求參數(shù)解析
響應(yīng)數(shù)據(jù)解析
驗證
發(fā)送Json/XMl
Json請求示例代碼
xml請求示例代碼
總結(jié)
資料獲取方法
寫在前面
上一篇我們介紹了使用?net/http
?發(fā)送get請求,因為考慮到篇幅問題,把Post單獨(dú)拎了出來,我們在這一篇一起從源碼來了解一下Golang的Post請求。
發(fā)送Post請求
net/http
發(fā)送Post請求很容易,下面的代碼我們和Get請求一樣,把響應(yīng)的內(nèi)容的信息打印出來了,細(xì)心的朋友可能會發(fā)現(xiàn),在參數(shù)傳遞、和結(jié)果解析時用了三種不同的方式,我們將在后面進(jìn)行解析。
示例代碼
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
)
func main() {
resp, err := http.Post("http://httpbin.org/post",
"application/x-www-form-urlencoded",
strings.NewReader("name=Detector&mobile=1xxxxxxxx"))
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
headers := resp.Header
// headers 打印報文頭部信息
for k, v := range headers {
fmt.Printf("%v, %v\n", k, v) // %v 打印interfac{}的值
}
// 打印響應(yīng)信息內(nèi)容
fmt.Printf("響應(yīng)狀態(tài):%s,響應(yīng)碼: %d\n", resp.Status, resp.StatusCode)
fmt.Printf("協(xié)議:%s\n", resp.Proto)
fmt.Printf("響應(yīng)內(nèi)容長度: %d\n", resp.ContentLength)
fmt.Printf("編碼格式:%v\n", resp.TransferEncoding) // 未指定時為空
fmt.Printf("是否壓縮:%t\n", resp.Uncompressed)
fmt.Println(reflect.TypeOf(resp.Body)) // *http.gzipReader
fmt.Println(resp.Body)
buf := bytes.NewBuffer(make([]byte, 0, 512))
length, _ := buf.ReadFrom(resp.Body)
fmt.Println(len(buf.Bytes()))
fmt.Println(length)
fmt.Println(string(buf.Bytes()))
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
源碼分析
Post請求參數(shù)解析
我們首先來看一下C:\Go\src\net\http\client.go
中Post和Get請求的源碼:
func Get(url string) (resp *Response, err error) {
return DefaultClient.Get(url)
}
func Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
return DefaultClient.Post(url, contentType, body)
}
從上面的定義可以看出,Post請求的參數(shù)比Get復(fù)雜一些,不僅要傳遞string類型contentType
還有傳遞io.Reader
類型的body體。可能有的小伙伴就有疑問了--?io.Reader
類型的body體是不是意味著我們一定要使用io.Reader
模塊來獲取數(shù)據(jù)呢?
答案當(dāng)然是否定的。
我們通過閱讀源碼,來找想要的答案。
找到其最小粒度的接口是一個比較好的手段,io.Reader
最小粒度的接口的定義在C:\Go\src\io\io.go
中:
type Reader interface {
Read(p []byte) (n int, err error)
}
在我前面的一篇博客【Golang】基礎(chǔ)10 Go語言最精妙的設(shè)計--interface中學(xué)習(xí)過 interface,其中有兩句話是這樣的:
interface類型定義了一組方法,如果某個對象實現(xiàn)了某個接口的所有方法,則此對象就實現(xiàn)了此接口。如果我們定義了一個interface的變量,那么這個變量里面可以存實現(xiàn)這個interface的任意類型的對象。
針對io.Reader
的定義翻譯一下就是,只要實現(xiàn)了Read(p []byte) (n int, err error)
方法的類型,就可以存儲io.Reader
,從而作為Post請求的Body參數(shù)。
我們接著來看看響應(yīng)resp中數(shù)據(jù)的定義。
響應(yīng)數(shù)據(jù)解析
在上一篇我們對http請求中的數(shù)據(jù)進(jìn)行了介紹,這一次我們針對resp.Body
進(jìn)行展開。
在C:\Go\src\net\http\response.go
中我們可以看到它的類型Body io.ReadCloser
,在C:\Go\src\io\io.go
中我們可以看到對應(yīng)的定義是這樣的:
type ReadCloser interface {
Reader
Closer
}
而Reader就是我們上面分析的過的請求body定義的Reader,而Closer是一個error
類型:
type Closer interface {
Close() error
}
根據(jù)我們上面的結(jié)論--?定義的某個接口的變量可以存儲同樣實現(xiàn)該接口的任意類型對象,即是說任意類型,只要實現(xiàn)了?Reader和?Closer?即可以用來解析resp.Body
。
那我們來驗證一下示例里面使用的三種方法是不是符合我們這個結(jié)論。
驗證
-
strings.NewReader
我們可以在C:\Go\src\strings\reader.go
看到?Reader類型的?Read
方法: -
bytes.NewBuffer
我們可以在C:\Go\src\bytes\buffer.go
看到?Buffer類型的?Read
方法: -
ioutil.ReadAll
我們可以在C:\Go\src\io\ioutil\ioutil.go
看到?io.Reader類型的?ReadAll
和Close() error
方法:
發(fā)送Json/XMl
在了解了上面的知識之后,我們再來看發(fā)送Json、XML數(shù)據(jù)等就比較簡單了。
Json請求示例代碼
func JsonReq() {
info := make(map[string]interface{})
info["name"] = "Detector"
info["age"] = 15
info["loc"] = "深圳"
// 將map解析未[]byte類型
bytesData, _ := json.Marshal(info)
// 將解析之后的數(shù)據(jù)轉(zhuǎn)為*Reader類型
reader := bytes.NewReader(bytesData)
println(reader)
resp, _ := http.Post("http://httpbin.org/post",
"application/json",
reader)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
代碼里面給了一些注釋,我們把要發(fā)送的數(shù)據(jù)轉(zhuǎn)化為了?*Reader
類型,然后就可以直接發(fā)送了。(我們從上面的源碼分析可以知道這個類型是可以存儲io.Reader
的數(shù)據(jù)的)
xml請求示例代碼
func XMLReq() {
xml := `<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="VideoLoading">Loading video…</string>
<string name="ApplicationName">what</string>
</resources>`
bytesData := strings.NewReader(xml)
resp, _ := http.Post("http://httpbin.org/post",
"application/xml",
bytesData)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
總結(jié)
- Json、xml請求
- 請求、響應(yīng)數(shù)據(jù)簡析
- interface概念復(fù)習(xí)
資料獲取方法
【留言777】
各位想獲取源碼等教程資料的朋友請點(diǎn)贊 + 評論 + 收藏,三連!文章來源:http://www.zghlxwxcb.cn/news/detail-620710.html
三連之后我會在評論區(qū)挨個私信發(fā)給你們~文章來源地址http://www.zghlxwxcb.cn/news/detail-620710.html
到了這里,關(guān)于【Golang 接口自動化02】使用標(biāo)準(zhǔn)庫net/http發(fā)送Post請求的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!