golang的httpclient怎么發(fā)起http請求

這篇文章主要講解了“golang的httpclient怎么發(fā)起http請求”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“golang的httpclient怎么發(fā)起http請求”吧!

創(chuàng)新互聯(lián)建站專注于津南網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供津南營銷型網(wǎng)站建設(shè),津南網(wǎng)站制作、津南網(wǎng)頁設(shè)計、津南網(wǎng)站官網(wǎng)定制、成都微信小程序服務(wù),打造津南網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供津南網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

一、net/http的httpclient發(fā)起http請求

方法

get請求

func httpGet() {

    resp, err := http.Get("http://www.01happy.com/demo/accept.php?id=1")

    if err != nil {

        // handle error

    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        // handle error

    }

    fmt.Println(string(body))

}

post請求 

方法一:http.Post方法

func httpPost() {

    resp, err := http.Post("http://www.01happy.com/demo/accept.php",

        "application/x-www-form-urlencoded",

        strings.NewReader("name=cjb"))

    if err != nil {

        fmt.Println(err)

    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        // handle error

    }

    fmt.Println(string(body))

}

使用這個方法,第二個參數(shù)(contentType)必須設(shè)置為"application/x-www-form-urlencoded",否則post參數(shù)無法傳遞

方法二:http.PostForm方法

func httpPostForm() {

    resp, err := http.PostForm("http://www.01happy.com/demo/accept.php",

        url.Values{"key": {"Value"}, "id": {"123"}})

    if err != nil {

        // handle error

    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        // handle error

    }

    fmt.Println(string(body))

}

復(fù)雜的請求:若需要設(shè)置請求頭參數(shù),cookie之類的數(shù)據(jù),就使用http.Do方法

func httpDo() {

    client := &http.Client{}

    req, err := http.NewRequest("POST", "http://www.01happy.com/demo/accept.php", strings.NewReader("name=cjb"))

    if err != nil {

        // handle error

    }

    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    req.Header.Set("Cookie", "name=anny")

    resp, err := client.Do(req)

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        // handle error

    }

    fmt.Println(string(body))

}

Head請求:Head方法,只返回頁面的首部

注意: 

要調(diào)用resp.Body.Close()關(guān)閉response.body。如果resp.body沒有關(guān)閉,則Client底層RoundTripper將無法重用存在的TCP連接去服務(wù)接下來的請求

第二步:Do/Get/Post方法的實現(xiàn)(以Do為例)

處理請求,添加referer、method字段

調(diào)用send方法,向request添加cookie

檢查http頭是否合法,若合法調(diào)用transport的RoundTrip方法

第三步:精髓:調(diào)用transport的RoundTrip方法

++transport.go:++

struct:

type Transport struct {

    idleMu     sync.Mutex

    wantIdle   bool // user has requested to close all idle conns

    idleConn   map[connectMethodKey][]*persistConn

    idleConnCh map[connectMethodKey]chan *persistConn

    reqMu       sync.Mutex

    reqCanceler map[*Request]func()

    altMu    sync.RWMutex

    altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper

    //Dial獲取一個tcp 連接,也就是net.Conn結(jié)構(gòu),你就記住可以往里面寫request

    //然后從里面搞到response就行了

    Dial func(network, addr string) (net.Conn, error)

}

兩個map: 

idleConn:保存從 connectMethodKey (代表著不同的協(xié)議 不同的host,也就是不同的請求)到 persistConn 的映射

idleConnCh:用來在并發(fā)http請求的時候在多個 goroutine 里面相互發(fā)送持久連接,也就是說, 這些持久連接是可以重復(fù)利用的, 你的http請求用某個persistConn用完了,通過這個channel發(fā)送給其他http請求使用這個persistConn

==連接池:==

RoundTrip方法:

func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {

    ...

    pconn, err := t.getConn(req, cm)

    if err != nil {

        t.setReqCanceler(req, nil)

        req.closeBody()

        return nil, err

    }

    return pconn.roundTrip(treq)

}

省略前面對參數(shù)的檢查部分,主要有兩步:

第一步:獲取TCP長連接pconn, err := t.getConn(req, cm)

func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error) {

    ...

    type dialRes struct {

        pc  *persistConn

        err error

    }

    dialc := make(chan dialRes)

    //定義了一個發(fā)送 persistConn的channel

    ...

    // 啟動了一個goroutine, 這個goroutine 獲取里面調(diào)用dialConn搞到

    // persistConn, 然后發(fā)送到上面建立的channel  dialc里面,    

    go func() {

        pc, err := t.dialConn(cm)

        dialc <- dialRes{pc, err}

    }()

    idleConnCh := t.getIdleConnCh(cm)

    select {

    case v := <-dialc:

        // dialc 我們的 dial 方法先搞到通過 dialc通道發(fā)過來了

        return v.pc, v.err

    case pc := <-idleConnCh:

        // 這里代表其他的http請求用完了歸還的persistConn通過idleConnCh這個    

        // channel發(fā)送來的

        handlePendingDial()

        return pc, nil

    case <-req.Cancel:

        handlePendingDial()

        return nil, errors.New("net/http: request canceled while waiting for connection")

    case <-cancelc:

        handlePendingDial()

        return nil, errors.New("net/http: request canceled while waiting for connection")

    }

}

定義一個發(fā)送 persistConn的channel dialc

啟動了一個goroutine, 這個goroutine 獲取里面調(diào)用dialConn搞到persistConn, 然后發(fā)送到dialc里面

主協(xié)程goroutine在 select里面監(jiān)聽多個channel,看看哪個通道里面先發(fā)過來 persistConn,就用哪個,然后return

第二步:調(diào)用這個持久連接persistConn 這個struct的roundTrip方法

三個goroutine通過channel互相協(xié)作的過程, 

1. 主goroutine ->requestAndChan -> 讀循環(huán)goroutine:讀循環(huán)goroutine 通過channel requestAndChan 接受主goroutine發(fā)送的request(rc := <-pc.reqch), 并從tcp輸出流中讀取response, 然后反序列化到結(jié)構(gòu)體中, 最后通過channel 返給主goroutine (rc.ch <- responseAndError{resp, err} ) 

2. 主goroutine ->writeRequest-> 寫循環(huán)goroutine:select channel中主gouroutine的request,然后寫入tcp輸入流,如果出錯了,channel 通知調(diào)用者 

3. 主goroutine 通過select 監(jiān)聽各個channel上的數(shù)據(jù), 比如請求取消, timeout,長連接掛了,寫流出錯,讀流出錯, 都是其他goroutine 發(fā)送過來的, 跟中斷一樣,然后相應(yīng)處理

二、使用net/http的參數(shù)設(shè)置:

粗粒度: 

使用http.Client的 Timeout字段。 

它的時間計算包括從連接(Dial)到讀完response body。

細粒度:細粒度只對于單次連接起作用

net.Dialer.Timeout 限制建立TCP連接的時間

http.Transport.TLSHandshakeTimeout 限制 TLS握手的時間

http.Transport.ResponseHeaderTimeout 限制讀取response header的時間

http.Transport.ExpectContinueTimeout 限制client在發(fā)送包含 Expect: 100-continue的header到收到繼續(xù)發(fā)送body的response之間的時間等待。

http.Transport.IdleConnTimeout,控制連接池中一個連接可以idle多長時間。

http.Client的默認超時時限是0,不超時,可以設(shè)置。

實際上是一個連接池,全局復(fù)用。初始化Transport,然后復(fù)用

參數(shù):

DisableKeepAlives默認為false(長連接)

MaxIdleConns連接池對所有host的最大連接數(shù)量,默認無窮大

MaxIdleConnsPerHHost連接池對每個host的最大連接數(shù)量。(一個host的情況下最好與上面保持一致)

IdleConnTimeout空閑時間設(shè)置

函數(shù):

DialContext用于創(chuàng)建(http)連接。

感謝各位的閱讀,以上就是“golang的httpclient怎么發(fā)起http請求”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對golang的httpclient怎么發(fā)起http請求這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

新聞標題:golang的httpclient怎么發(fā)起http請求
分享網(wǎng)址:http://muchs.cn/article44/geedhe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、定制開發(fā)網(wǎng)站收錄、外貿(mào)網(wǎng)站建設(shè)小程序開發(fā)、Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作