标签:ESS 方法 one close amp err 路由 转换 引用
目录:
1
2
3
|
type Handler interface { ServeHTTP(ResponseWriter, *Request) } |
1
2
3
4
5
|
type HandlerFunc func (ResponseWriter, *Request) //实现Handler接口的ServeHTTP方法 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) //调用自身 } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
mux := http.NewServeMux() mux.Handle( "/file" ,myHandler( "somefile" )) mux.HandleFunc( "/" , serveHome) s := &http.Server{ Addr: ":8080" , Handler: mux, //指定路由或处理器,不指定时为nil,表示使用默认的路由DefaultServeMux ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, ConnState: //指定连接conn的状态改变时的处理函数 //.... } log.Fatal(s.ListenAndServe()) |
接下来,我们就跟踪源码来仔细的分析下整个执行过程。
1
2
3
4
|
func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } |
2.而server.ListenAndServe()方法内部调用net.Listen("tcp", addr),该方法内部又调用net.ListenTCP()创建并返回一个监听器net.Listener,如下的ln;
1
2
3
4
5
6
7
8
9
10
11
|
func (srv *Server) ListenAndServe() error { addr := srv.Addr if addr == "" { addr = ":http" } ln, err := net.Listen( "tcp" , addr) if err != nil { return err } return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) } |
1
2
3
4
5
6
7
8
9
10
11
12
|
type tcpKeepAliveListener struct { *net.TCPListener } func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { tc, err := ln.AcceptTCP() if err != nil { return } tc.SetKeepAlive(true) //发送心跳 tc.SetKeepAlivePeriod(3 * time.Minute) //发送周期 return tc, nil } |
1
2
3
4
5
6
7
8
9
10
|
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { handler := sh.srv.Handler if handler == nil { handler = DefaultServeMux } if req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } handler.ServeHTTP(rw, req) } |
6.如上源码可以看到,当 handler == nil 时使用默认的DefaultServeMux路由,否则使用在第1步中为Serve指定了的Handler;然后调用该Handler的ServeHTTP方法(该Handler一般被设置为路由ServeMux类型);
1
2
3
4
5
6
7
8
9
10
11
|
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI == "*" { if r.ProtoAtLeast(1, 1) { w.Header().Set( "Connection" , "close" ) } w.WriteHeader(StatusBadRequest) return } h, _ := mux.Handler(r) //规范化请求的路径格式,查找最匹配的Handler h.ServeHTTP(w, r) } |
1
2
3
4
5
|
type HandlerFunc func (ResponseWriter, *Request) //实现Handler接口的ServeHTTP方法 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) //调用自身 } |
1
2
3
4
5
6
7
8
|
func main() { mux := http.NewServeMux() mux.Handle( "/to" ,http.RedirectHandler( "http://example.org" , 307)) err := http.ListenAndServe(*addr,mux) //启动监听 if err != nil { log.Fatalln( "ListenAndServe: " , err) } } |
Get、Head、Post和PostForm函数发出HTTP/ HTTPS请求。
1
2
3
4
5
6
|
resp, err := http.Get( "http://example.com/" ) ... resp, err := http.Post( "http://example.com/upload" , "image/jpeg" , &buf) ... resp, err := http.PostForm( "http://example.com/form" , url.Values{ "key" : { "Value" }, "id" : { "123" }}) |
程序在使用完回复后必须关闭回复的主体。
1
2
3
4
5
6
7
|
resp, err := http.Get( "http://example.com/" ) if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) // ... |
要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client:
1
2
3
4
5
6
7
8
9
10
|
client := &http.Client{ CheckRedirect: redirectPolicyFunc, } resp, err := client.Get( "http://example.com" ) // ... req, err := http.NewRequest( "GET" , "http://example.com" , nil) // ... req.Header.Add( "If-None-Match" , `W/ "wyzzy" `) resp, err := client.Do(req) // ... |
要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:
1
2
3
4
5
6
|
tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: pool}, DisableCompression: true, } client := &http.Client{Transport: tr} resp, err := client.Get( "https://example.com" ) |
Client和Transport类型都可以安全的被多个go程同时使用。出于效率考虑,应该一次建立、尽量重用。
参考:https://blog.csdn.net/weixin_34302561/article/details/89749438
标签:ESS 方法 one close amp err 路由 转换 引用
原文地址:https://www.cnblogs.com/show58/p/12627808.html