> 백엔드 개발 > Golang > Go의 http 클라이언트 구문 분석

Go의 http 클라이언트 구문 분석

藏色散人
풀어 주다: 2021-05-10 21:56:23
앞으로
4896명이 탐색했습니다.

다음 튜토리얼 칼럼인 golang에서는 Go의 http 클라이언트를 소개하겠습니다. 필요한 친구들에게 도움이 되길 바랍니다!

Go는 HTTP 클라이언트를 캡슐화하여 소스 코드의 하위 계층을 보면 원격 데이터를 요청하는 것이 매우 편리합니다.
resp, err := http.Get("https://baidu.com") if err != nil {
    fmt.Printf("发起请求失败:%v", err)
    return }defer resp.Body.Close() io.Copy(os.Stdout, resp.Body)
로그인 후 복사
요청의 일반적인 프로세스

1. 요청 조건에 따라 요청 개체를 구성합니다

2. 모든 클라이언트 요청은 client.do()

func (c *Client) do(req *Request) (retres *Response, reterr error)
로그인 후 복사

2.1 요청 요청에 의해 처리됩니다. client.send() 처리

func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTimeout func() bool, err error)resp, didTimeout, err = send(req, c.transport(), deadline)//默认传DefaultTransport
로그인 후 복사
3.send 함수
func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, didTimeout func() bool, err error) {
    resp, err = rt.RoundTrip(req) }
로그인 후 복사

4.DefaultTransport의 RoundTrip 메서드는 실제로 Transport의 RoundTrip 메서드

func (t *Transport) roundTrip(req *Request) (*Response, error) {
    treq := &transportRequest{Request: req, trace: trace} //封装新的request
    cm, err := t.connectMethodForRequest(treq)
    pconn, err := t.getConn(treq, cm) //使用连接池技术,获取连接对象*persistConn,
    resp, err = pconn.roundTrip(treq) //使用连接对象获取response}
로그인 후 복사

5를 사용하여 연결 개체 *persistConn

을 얻습니다.
func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persistConn, err error) {
    w := &wantConn{ //构建连接对象
        cm:         cm,
        key:        cm.key(),
        ctx:        ctx,
        ready:      make(chan struct{}, 1),
        beforeDial: testHookPrePendingDial,
        afterDial:  testHookPostPendingDial,
    }
    if delivered := t.queueForIdleConn(w); delivered {//从连接池获取符合的连接对象,有就返回
        pc := w.pc        
        return pc, nil
    }    
    t.queueForDial(w)//发起连接

    select {
    case <-w.ready:    //连接准备好,就返回连接对象    
        return w.pc, w.err}
로그인 후 복사
S 5.1 Transport.queueFordial은 DialConnFor

R
func (t *Transport) queueForDial(w *wantConn) {
    go t.dialConnFor(w)}
로그인 후 복사
E

5.3 다이얼을 시작하기 위해
func (t *Transport) dialConnFor(w *wantConn) {
    pc, err := t.dialConn(w.ctx, w.cm) //发起拨号,返回连接对象
    delivered := w.tryDeliver(pc, err)}
로그인 후 복사
5.2 연결을 시작했습니다. 공개할 코루틴
func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *persistConn, err error) {
    pconn = &persistConn{ //构建连接对象
        t:             t,
        cacheKey:      cm.key(),
        reqch:         make(chan requestAndChan, 1),
        writech:       make(chan writeRequest, 1),
        closech:       make(chan struct{}),
        writeErrCh:    make(chan error, 1),
        writeLoopDone: make(chan struct{}),
    }
    conn, err := t.dial(ctx, "tcp", cm.addr()) //tcp连接,获取到net.conn对象

    pconn.br = bufio.NewReaderSize(pconn, t.readBufferSize())//可以从conn读
    pconn.bw = bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize())//写到conn

    go pconn.readLoop()//开启读协程
    go pconn.writeLoop()//开启写协程
    return pconn, nil}
로그인 후 복사
E
5.4.1 응답을 얻기 위한 PC.ReadResponse
func (pc *persistConn) readLoop() {
    alive := true
    for alive {
        rc := <-pc.reqch //读取request,写入的地方在步骤6

        resp, err = pc.readResponse(rc, trace) //返回response
        //response的body是否可写,服务器code101才可写,所以正常这个是false
        bodyWritable := resp.bodyIsWritable()

        //response.Close设置循环结束,退出协程
        if resp.Close || rc.req.Close || resp.StatusCode <= 199 || bodyWritable {                    alive = false
        }          

        //把response写入通道,在步骤6会读取这个通道
        select {
        case rc.ch <- responseAndError{res: resp}:
        case <-rc.callerGone:
            return
        }
        //循环结束的一些情况
        select {
        case bodyEOF := <-waitForBodyRead: //读完body也会自动结束            
        case <-rc.req.Cancel:
        case <-rc.req.Context().Done():
        case <-pc.closech:
            alive = false
            pc.t.CancelRequest(rc.req)
        }
    }
로그인 후 복사
5.4.2 ReadResponse
6. 연결 객체를 사용하여 *persistConn을 사용하세요.

위 내용은 Go의 http 클라이언트 구문 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:learnku.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿