这篇文章主要讲解了“golang的httpclient怎么发起http请求”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang的httpclient怎么发起http请求”吧!一、net/http的httpclient发起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))}使用这个方法,第二个参数(contentType)必须设置为”application/x-www-form-urlencoded”,否则post参数无法传递方法二: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))}复杂的请求:若需要设置请求头参数,cookie之类的数据,就使用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方法,只返回页面的首部注意:要调用resp.Body.Close()关闭response.body。如果resp.body没有关闭,则Client底层RoundTripper将无法重用存在的TCP连接去服务接下来的请求第二步:Do/Get/Post方法的实现(以Do为例)处理请求,添加referer、method字段调用send方法,向request添加cookie检查http头是否合法,若合法调用transport的RoundTrip方法第三步:精髓:调用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结构,你就记住可以往里面写request //然后从里面搞到response就行了 Dial func(network, addr string) (net.Conn, error)}两个map:idleConn:保存从 connectMethodKey (代表着不同的协议 不同的host,也就是不同的请求)到 persistConn 的映射idleConnCh:用来在并发http请求的时候在多个 goroutine 里面相互发送持久连接,也就是说, 这些持久连接是可以重复利用的, 你的http请求用某个persistConn用完了,通过这个channel发送给其他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)}省略前面对参数的检查部分,主要有两步:第一步:获取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) //定义了一个发送 persistConn的channel … // 启动了一个goroutine, 这个goroutine 获取里面调用dialConn搞到 // persistConn, 然后发送到上面建立的channel dialc里面, go func() { pc, err := t.dialConn(cm) dialc
}() idleConnCh := t.getIdleConnCh(cm) select { case v :=
// dialc 我们的 dial 方法先搞到通过 dialc通道发过来了 return v.pc, v.err case pc :=
// 这里代表其他的http请求用完了归还的persistConn通过idleConnCh这个 // channel发送来的 handlePendingDial() return pc, nil case
handlePendingDial() return nil, errors.New(“net/http: request canceled while waiting for connection”) case
handlePendingDial() return nil, errors.New(“net/http: request canceled while waiting for connection”) }}定义一个发送 persistConn的channel dialc启动了一个goroutine, 这个goroutine 获取里面调用dialConn搞到persistConn, 然后发送到dialc里面主协程goroutine在 select里面监听多个channel,看看哪个通道里面先发过来 persistConn,就用哪个,然后return第二步:调用这个持久连接persistConn 这个struct的roundTrip方法三个goroutine通过channel互相协作的过程,1. 主goroutine ->requestAndChan -> 读循环goroutine:读循环goroutine 通过channel requestAndChan 接受主goroutine发送的request(rc :=
2. 主goroutine ->writeRequest-> 写循环goroutine:select channel中主gouroutine的request,然后写入tcp输入流,如果出错了,channel 通知调用者3. 主goroutine 通过select 监听各个channel上的, 比如请求取消, timeout,长连接挂了,写流出错,读流出错, 都是其他goroutine 发送过来的, 跟中断一样,然后相应处理二、使用net/http的参数设置:粗粒度:使用http.Client的 Timeout字段。它的时间计算包括从连接(Dial)到读完response body。细粒度:细粒度只对于单次连接起作用net.Dialer.Timeout 限制建立TCP连接的时间http.Transport.TLSHandshakeTimeout 限制 TLS握手的时间http.Transport.ResponseHeaderTimeout 限制读取response header的时间http.Transport.ExpectContinueTimeout 限制client在发送包含 Expect: 100-continue的header到收到继续发送body的response之间的时间等待。http.Transport.IdleConnTimeout,控制连接池中一个连接可以idle多长时间。http.Client的默认超时时限是0,不超时,可以设置。实际上是一个连接池,全局复用。初始化Transport,然后复用参数:DisableKeepAlives默认为false(长连接)MaxIdleConns连接池对所有host的最大连接数量,默认无穷大MaxIdleConnsPerHHost连接池对每个host的最大连接数量。(一个host的情况下最好与上面保持一致)IdleConnTimeout空闲时间设置函数:DialContext用于创建(http)连接。感谢各位的阅读,以上就是“golang的ht 香港云主机tpclient怎么发起http请求”的内容了,经过本文的学习后,相信大家对golang的httpclient怎么发起http请求这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是开发云,小编将为大家推送更多相关知识点的文章,欢迎关注!

相关

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。