golang httpclient.go

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang httpclient.go相关的知识,希望对你有一定的参考价值。

package httptimeout

import (
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

func TestHttpTimeout(t *testing.T) {
	http.HandleFunc("/normal", func(w http.ResponseWriter, req *http.Request) {
		// Empirically, timeouts less than these seem to be flaky
		time.Sleep(100 * time.Millisecond)
		io.WriteString(w, "ok")
	})
	http.HandleFunc("/timeout", func(w http.ResponseWriter, req *http.Request) {
		time.Sleep(250 * time.Millisecond)
		io.WriteString(w, "ok")
	})
	ts := httptest.NewServer(http.DefaultServeMux)
	defer ts.Close()

	numDials := 0

	client := &http.Client{
		Transport: &TimeoutTransport{
			Transport: http.Transport{
				Dial: func(netw, addr string) (net.Conn, error) {
					t.Logf("dial to %s://%s", netw, addr)
					numDials++ // For testing only.
					return net.Dial(netw, addr) // Regular ass dial.
				},
			},
			RoundTripTimeout: time.Millisecond * 200,
		},
	}

	addr := ts.URL

	SendTestRequest(t, client, "1st", addr, "normal")
	if numDials != 1 {
		t.Fatalf("Should only have 1 dial at this point.")
	}
	SendTestRequest(t, client, "2st", addr, "normal")
	if numDials != 1 {
		t.Fatalf("Should only have 1 dial at this point.")
	}
	SendTestRequest(t, client, "3st", addr, "timeout")
	if numDials != 1 {
		t.Fatalf("Should only have 1 dial at this point.")
	}
	SendTestRequest(t, client, "4st", addr, "normal")
	if numDials != 2 {
		t.Fatalf("Should have our 2nd dial.")
	}

	time.Sleep(time.Millisecond * 700)

	SendTestRequest(t, client, "5st", addr, "normal")
	if numDials != 2 {
		t.Fatalf("Should still only have 2 dials.")
	}
}

func SendTestRequest(t *testing.T, client *http.Client, id, addr, path string) {
	req, err := http.NewRequest("GET", addr+"/"+path, nil)

	if err != nil {
		t.Fatalf("new request failed - %s", err)
	}

	req.Header.Add("Connection", "keep-alive")

	switch path {
	case "normal":
		if resp, err := client.Do(req); err != nil {
			t.Fatalf("%s request failed - %s", id, err)
		} else {
			result, err2 := ioutil.ReadAll(resp.Body)
			if err2 != nil {
				t.Fatalf("%s response read failed - %s", id, err2)
			}
			resp.Body.Close()
			t.Logf("%s request - %s", id, result)
		}
	case "timeout":
		if _, err := client.Do(req); err == nil {
			t.Fatalf("%s request not timeout", id)
		} else {
			t.Logf("%s request - %s", id, err)
		}
	}
}
package httptimeout

import (
	"net/http"
	"time"
	"fmt"
)

type TimeoutTransport struct {
	http.Transport
	RoundTripTimeout time.Duration
}

type respAndErr struct {
	resp *http.Response
	err error
}

type netTimeoutError struct {
	error
}

func (ne netTimeoutError) Timeout() bool { return true }

// If you don't set RoundTrip on TimeoutTransport, this will always timeout at 0
func (t *TimeoutTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	timeout := time.After(t.RoundTripTimeout)
	resp := make(chan respAndErr, 1)

	go func() {
		r, e := t.Transport.RoundTrip(req)
		resp <- respAndErr{
			resp: r,
			err: e,
		}
	}()

	select {
	case <-timeout:// A round trip timeout has occurred.
		t.Transport.CancelRequest(req)
		return nil, netTimeoutError{
			error: fmt.Errorf("timed out after %s", t.RoundTripTimeout),
		}
	case r := <-resp: // Success!
		return r.resp, r.err
	}
}

golang为啥没有官方的gui包

有两个方面的原因,一是golang gui想让第三方来做 , 二是官方对golang的定位是主做后台。。。 参考技术A 因为golang官方主要把精力投入到go本身的发展中去(更准确的GC算法、更高的并发)。 而golang的主要贡献者不多,所以还不是很忙的过来,golang官方希望GUI可以靠社区推动发展,官方本身是没有意向发布GUI包的。

以上是关于golang httpclient.go的主要内容,如果未能解决你的问题,请参考以下文章

Golang 入门

Golang入门到项目实战 第一个golang应用

golang编译androidso无法加载

golang如何打印内存内容

Golang入门到项目实战 golang匿名函数

json [Golang] golang #golang #snippets中有用的片段