<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # package http `import "net/http"` http包提供了HTTP客戶端和服務端的實現。 Get、Head、Post和PostForm函數發出HTTP/ HTTPS請求。 ``` 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"}}) ``` 程序在使用完回復后必須關閉回復的主體。 ``` resp, err := http.Get("http://example.com/") if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) // ... ``` 要管理HTTP客戶端的頭域、重定向策略和其他設置,創建一個Client: ``` 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: ``` 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程同時使用。出于效率考慮,應該一次建立、盡量重用。 ListenAndServe使用指定的監聽地址和處理器啟動一個HTTP服務端。處理器參數通常是nil,這表示采用包變量DefaultServeMux作為處理器。Handle和HandleFunc函數可以向DefaultServeMux添加處理器。 ``` http.Handle("/foo", fooHandler) http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) }) log.Fatal(http.ListenAndServe(":8080", nil)) ``` 要管理服務端的行為,可以創建一個自定義的Server: ``` s := &http.Server{ Addr: ":8080", Handler: myHandler, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } log.Fatal(s.ListenAndServe()) ``` ## Index * [Constants](#pkg-constants) * [Variables](#pkg-variables) * [type ProtocolError](#ProtocolError) * [func (err \*ProtocolError) Error() string](#ProtocolError.Error) * [func CanonicalHeaderKey(s string) string](#CanonicalHeaderKey) * [func DetectContentType(data []byte) string](#DetectContentType) * [func ParseHTTPVersion(vers string) (major, minor int, ok bool)](#ParseHTTPVersion) * [func ParseTime(text string) (t time.Time, err error)](#ParseTime) * [func StatusText(code int) string](#StatusText) * [type ConnState](#ConnState) * [func (c ConnState) String() string](#ConnState.String) * [type Header](#Header) * [func (h Header) Get(key string) string](#Header.Get) * [func (h Header) Set(key, value string)](#Header.Set) * [func (h Header) Add(key, value string)](#Header.Add) * [func (h Header) Del(key string)](#Header.Del) * [func (h Header) Write(w io.Writer) error](#Header.Write) * [func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error](#Header.WriteSubset) * [type Cookie](#Cookie) * [func (c \*Cookie) String() string](#Cookie.String) * [type CookieJar](#CookieJar) * [type Request](#Request) * [func NewRequest(method, urlStr string, body io.Reader) (\*Request, error)](#NewRequest) * [func ReadRequest(b \*bufio.Reader) (req \*Request, err error)](#ReadRequest) * [func (r \*Request) ProtoAtLeast(major, minor int) bool](#Request.ProtoAtLeast) * [func (r \*Request) UserAgent() string](#Request.UserAgent) * [func (r \*Request) Referer() string](#Request.Referer) * [func (r \*Request) AddCookie(c \*Cookie)](#Request.AddCookie) * [func (r \*Request) SetBasicAuth(username, password string)](#Request.SetBasicAuth) * [func (r \*Request) Write(w io.Writer) error](#Request.Write) * [func (r \*Request) WriteProxy(w io.Writer) error](#Request.WriteProxy) * [func (r \*Request) Cookies() []\*Cookie](#Request.Cookies) * [func (r \*Request) Cookie(name string) (\*Cookie, error)](#Request.Cookie) * [func (r \*Request) ParseForm() error](#Request.ParseForm) * [func (r \*Request) ParseMultipartForm(maxMemory int64) error](#Request.ParseMultipartForm) * [func (r \*Request) FormValue(key string) string](#Request.FormValue) * [func (r \*Request) PostFormValue(key string) string](#Request.PostFormValue) * [func (r \*Request) FormFile(key string) (multipart.File, \*multipart.FileHeader, error)](#Request.FormFile) * [func (r \*Request) MultipartReader() (\*multipart.Reader, error)](#Request.MultipartReader) * [type Response](#Response) * [func ReadResponse(r \*bufio.Reader, req \*Request) (\*Response, error)](#ReadResponse) * [func (r \*Response) ProtoAtLeast(major, minor int) bool](#Response.ProtoAtLeast) * [func (r \*Response) Cookies() []\*Cookie](#Response.Cookies) * [func (r \*Response) Location() (\*url.URL, error)](#Response.Location) * [func (r \*Response) Write(w io.Writer) error](#Response.Write) * [type ResponseWriter](#ResponseWriter) * [type Flusher](#Flusher) * [type CloseNotifier](#CloseNotifier) * [type Hijacker](#Hijacker) * [type RoundTripper](#RoundTripper) * [type Transport](#Transport) * [func (t \*Transport) RegisterProtocol(scheme string, rt RoundTripper)](#Transport.RegisterProtocol) * [func (t \*Transport) RoundTrip(req \*Request) (resp \*Response, err error)](#Transport.RoundTrip) * [func (t \*Transport) CloseIdleConnections()](#Transport.CloseIdleConnections) * [func (t \*Transport) CancelRequest(req \*Request)](#Transport.CancelRequest) * [type Client](#Client) * [func (c \*Client) Do(req \*Request) (resp \*Response, err error)](#Client.Do) * [func (c \*Client) Head(url string) (resp \*Response, err error)](#Client.Head) * [func (c \*Client) Get(url string) (resp \*Response, err error)](#Client.Get) * [func (c \*Client) Post(url string, bodyType string, body io.Reader) (resp \*Response, err error)](#Client.Post) * [func (c \*Client) PostForm(url string, data url.Values) (resp \*Response, err error)](#Client.PostForm) * [type Handler](#Handler) * [func NotFoundHandler() Handler](#NotFoundHandler) * [func RedirectHandler(url string, code int) Handler](#RedirectHandler) * [func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler](#TimeoutHandler) * [func StripPrefix(prefix string, h Handler) Handler](#StripPrefix) * [type HandlerFunc](#HandlerFunc) * [func (f HandlerFunc) ServeHTTP(w ResponseWriter, r \*Request)](#HandlerFunc.ServeHTTP) * [type ServeMux](#ServeMux) * [func NewServeMux() \*ServeMux](#NewServeMux) * [func (mux \*ServeMux) Handle(pattern string, handler Handler)](#ServeMux.Handle) * [func (mux \*ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, \*Request))](#ServeMux.HandleFunc) * [func (mux \*ServeMux) Handler(r \*Request) (h Handler, pattern string)](#ServeMux.Handler) * [func (mux \*ServeMux) ServeHTTP(w ResponseWriter, r \*Request)](#ServeMux.ServeHTTP) * [type Server](#Server) * [func (s \*Server) SetKeepAlivesEnabled(v bool)](#Server.SetKeepAlivesEnabled) * [func (srv \*Server) Serve(l net.Listener) error](#Server.Serve) * [func (srv \*Server) ListenAndServe() error](#Server.ListenAndServe) * [func (srv \*Server) ListenAndServeTLS(certFile, keyFile string) error](#Server.ListenAndServeTLS) * [type File](#File) * [type FileSystem](#FileSystem) * [type Dir](#Dir) * [func (d Dir) Open(name string) (File, error)](#Dir.Open) * [func NewFileTransport(fs FileSystem) RoundTripper](#NewFileTransport) * [func FileServer(root FileSystem) Handler](#FileServer) * [func SetCookie(w ResponseWriter, cookie \*Cookie)](#SetCookie) * [func Redirect(w ResponseWriter, r \*Request, urlStr string, code int)](#Redirect) * [func NotFound(w ResponseWriter, r \*Request)](#NotFound) * [func Error(w ResponseWriter, error string, code int)](#Error) * [func ServeContent(w ResponseWriter, req \*Request, name string, modtime time.Time, content io.ReadSeeker)](#ServeContent) * [func ServeFile(w ResponseWriter, r \*Request, name string)](#ServeFile) * [func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser](#MaxBytesReader) * [func ProxyURL(fixedURL \*url.URL) func(\*Request) (\*url.URL, error)](#ProxyURL) * [func ProxyFromEnvironment(req \*Request) (\*url.URL, error)](#ProxyFromEnvironment) * [func Head(url string) (resp \*Response, err error)](#Head) * [func Get(url string) (resp \*Response, err error)](#Get) * [func Post(url string, bodyType string, body io.Reader) (resp \*Response, err error)](#Post) * [func PostForm(url string, data url.Values) (resp \*Response, err error)](#PostForm) * [func Handle(pattern string, handler Handler)](#Handle) * [func HandleFunc(pattern string, handler func(ResponseWriter, \*Request))](#HandleFunc) * [func Serve(l net.Listener, handler Handler) error](#Serve) * [func ListenAndServe(addr string, handler Handler) error](#ListenAndServe) * [func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error](#ListenAndServeTLS) ### Examples * [FileServer](#example-FileServer) * [FileServer (StripPrefix)](#example-FileServer--StripPrefix) * [Get](#example-Get) * [Hijacker](#example-Hijacker) * [ServeMux.Handle](#example-ServeMux-Handle) * [StripPrefix](#example-StripPrefix) ``` const ( StatusContinue = 100 StatusSwitchingProtocols = 101 StatusOK = 200 StatusCreated = 201 StatusAccepted = 202 StatusNonAuthoritativeInfo = 203 StatusNoContent = 204 StatusResetContent = 205 StatusPartialContent = 206 StatusMultipleChoices = 300 StatusMovedPermanently = 301 StatusFound = 302 StatusSeeOther = 303 StatusNotModified = 304 StatusUseProxy = 305 StatusTemporaryRedirect = 307 StatusBadRequest = 400 StatusUnauthorized = 401 StatusPaymentRequired = 402 StatusForbidden = 403 StatusNotFound = 404 StatusMethodNotAllowed = 405 StatusNotAcceptable = 406 StatusProxyAuthRequired = 407 StatusRequestTimeout = 408 StatusConflict = 409 StatusGone = 410 StatusLengthRequired = 411 StatusPreconditionFailed = 412 StatusRequestEntityTooLarge = 413 StatusRequestURITooLong = 414 StatusUnsupportedMediaType = 415 StatusRequestedRangeNotSatisfiable = 416 StatusExpectationFailed = 417 StatusTeapot = 418 StatusInternalServerError = 500 StatusNotImplemented = 501 StatusBadGateway = 502 StatusServiceUnavailable = 503 StatusGatewayTimeout = 504 StatusHTTPVersionNotSupported = 505 ) ``` HTTP狀態碼,參見[RFC 2616](http://tools.ietf.org/html/rfc2616) ``` const DefaultMaxHeaderBytes = 1 << 20 // 1 MB ``` DefaultMaxHeaderBytes是HTTP請求的頭域最大允許長度。可以通過設置Server.MaxHeaderBytes字段來覆蓋。 ``` const DefaultMaxIdleConnsPerHost = 2 ``` DefaultMaxIdleConnsPerHost是Transport的MaxIdleConnsPerHost的默認值。 ``` const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT" ``` TimeFormat是當解析或生產HTTP頭域中的時間時,用與time.Parse或time.Format函數的時間格式。這種格式類似time.RFC1123但強制采用GMT時區。 ## Variables ``` var ( ErrHeaderTooLong = &ProtocolError{"header too long"} ErrShortBody = &ProtocolError{"entity body too short"} ErrNotSupported = &ProtocolError{"feature not supported"} ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"} ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"} ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"} ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"} ) ``` HTTP請求的解析錯誤。 ``` var ( ErrWriteAfterFlush = errors.New("Conn.Write called after Flush") ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body") ErrHijacked = errors.New("Conn has been hijacked") ErrContentLength = errors.New("Conn.Write wrote more than the declared Content-Length") ) ``` 會被HTTP服務端返回的錯誤。 ``` var DefaultClient = &Client{} ``` DefaultClient是用于包函數Get、Head和Post的默認Client。 ``` var DefaultServeMux = NewServeMux() ``` DefaultServeMux是用于Serve的默認ServeMux。 ``` var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body") ``` 在Resquest或Response的Body字段已經關閉后,試圖從中讀取時,就會返回ErrBodyReadAfterClose。這個錯誤一般發生在:HTTP處理器中調用完ResponseWriter?接口的WriteHeader或Write后從請求中讀取數據的時候。 ``` var ErrHandlerTimeout = errors.New("http: Handler timeout") ``` 在處理器超時以后調用ResponseWriter接口的Write方法,就會返回ErrHandlerTimeout。 ``` var ErrLineTooLong = errors.New("header line too long") ``` ``` var ErrMissingFile = errors.New("http: no such file") ``` 當請求中沒有提供給FormFile函數的文件字段名,或者該字段名不是文件字段時,該函數就會返回ErrMissingFile。 ``` var ErrNoCookie = errors.New("http: named cookie not present") ``` ``` var ErrNoLocation = errors.New("http: no Location header in response") ``` ## type [ProtocolError](https://github.com/golang/go/blob/master/src/net/http/request.go#L38 "View Source") ``` type ProtocolError struct { ErrorString string } ``` HTTP請求解析錯誤。 ### func (\*ProtocolError) [Error](https://github.com/golang/go/blob/master/src/net/http/request.go#L42 "View Source") ``` func (err *ProtocolError) Error() string ``` ## func [CanonicalHeaderKey](https://github.com/golang/go/blob/master/src/net/http/header.go#L171 "View Source") ``` func CanonicalHeaderKey(s string) string ``` CanonicalHeaderKey函數返回頭域(表示為Header類型)的鍵s的規范化格式。規范化過程中讓單詞首字母和'-'后的第一個字母大寫,其余字母小寫。例如,"accept-encoding"規范化為"Accept-Encoding"。 ## func [DetectContentType](https://github.com/golang/go/blob/master/src/net/http/sniff.go#L21 "View Source") ``` func DetectContentType(data []byte) string ``` DetectContentType函數實現了[http://mimesniff.spec.whatwg.org/](http://mimesniff.spec.whatwg.org/)描述的算法,用于確定數據的Content-Type。函數總是返回一個合法的MIME類型;如果它不能確定數據的類型,將返回"application/octet-stream"。它最多檢查數據的前512字節。 ## func [ParseHTTPVersion](https://github.com/golang/go/blob/master/src/net/http/request.go#L448 "View Source") ``` func ParseHTTPVersion(vers string) (major, minor int, ok bool) ``` ParseHTTPVersion解析HTTP版本字符串。如"HTTP/1.0"返回(1, 0, true)。 ## func [ParseTime](https://github.com/golang/go/blob/master/src/net/http/header.go#L79 "View Source") ``` func ParseTime(text string) (t time.Time, err error) ``` ParseTime用3種格式TimeFormat, time.RFC850和time.ANSIC嘗試解析一個時間頭的值(如Date: header)。 ## func [StatusText](https://github.com/golang/go/blob/master/src/net/http/status.go#L118 "View Source") ``` func StatusText(code int) string ``` StatusText返回HTTP狀態碼code對應的文本,如220對應"OK"。如果code是未知的狀態碼,會返回""。 ## type [ConnState](https://github.com/golang/go/blob/master/src/net/http/server.go#L1614 "View Source") ``` type ConnState int ``` ConnState代表一個客戶端到服務端的連接的狀態。本類型用于可選的Server.ConnState回調函數。 ``` const ( // StateNew代表一個新的連接,將要立刻發送請求。 // 連接從這個狀態開始,然后轉變為StateAlive或StateClosed。 StateNew ConnState = iota // StateActive代表一個已經讀取了請求數據1到多個字節的連接。 // 用于StateAlive的Server.ConnState回調函數在將連接交付給處理器之前被觸發, // 等到請求被處理完后,Server.ConnState回調函數再次被觸發。 // 在請求被處理后,連接狀態改變為StateClosed、StateHijacked或StateIdle。 StateActive // StateIdle代表一個已經處理完了請求、處在閑置狀態、等待新請求的連接。 // 連接狀態可以從StateIdle改變為StateActive或StateClosed。 StateIdle // 代表一個被劫持的連接。這是一個終止狀態,不會轉變為StateClosed。 StateHijacked // StateClosed代表一個關閉的連接。 // 這是一個終止狀態。被劫持的連接不會轉變為StateClosed。 StateClosed ) ``` ### func (ConnState) [String](https://github.com/golang/go/blob/master/src/net/http/server.go#L1655 "View Source") ``` func (c ConnState) String() string ``` ## type [Header](https://github.com/golang/go/blob/master/src/net/http/header.go#L19 "View Source") ``` type Header map[string][]string ``` Header代表HTTP頭域的鍵值對。 ### func (Header) [Get](https://github.com/golang/go/blob/master/src/net/http/header.go#L38 "View Source") ``` func (h Header) Get(key string) string ``` Get返回鍵對應的第一個值,如果鍵不存在會返回""。如要獲取該鍵對應的值切片,請直接用規范格式的鍵訪問map。 ### func (Header) [Set](https://github.com/golang/go/blob/master/src/net/http/header.go#L30 "View Source") ``` func (h Header) Set(key, value string) ``` Set添加鍵值對到h,如鍵已存在則會用只有新值一個元素的切片取代舊值切片。 ### func (Header) [Add](https://github.com/golang/go/blob/master/src/net/http/header.go#L23 "View Source") ``` func (h Header) Add(key, value string) ``` Add添加鍵值對到h,如鍵已存在則會將新的值附加到舊值切片后面。 ### func (Header) [Del](https://github.com/golang/go/blob/master/src/net/http/header.go#L51 "View Source") ``` func (h Header) Del(key string) ``` Del刪除鍵值對。 ### func (Header) [Write](https://github.com/golang/go/blob/master/src/net/http/header.go#L56 "View Source") ``` func (h Header) Write(w io.Writer) error ``` Write以有線格式將頭域寫入w。 ### func (Header) [WriteSubset](https://github.com/golang/go/blob/master/src/net/http/header.go#L145 "View Source") ``` func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error ``` WriteSubset以有線格式將頭域寫入w。當exclude不為nil時,如果h的鍵值對的鍵在exclude中存在且其對應值為真,該鍵值對就不會被寫入w。 ## type [Cookie](https://github.com/golang/go/blob/master/src/net/http/cookie.go#L23 "View Source") ``` type Cookie struct { Name string Value string Path string Domain string Expires time.Time RawExpires string // MaxAge=0表示未設置Max-Age屬性 // MaxAge<0表示立刻刪除該cookie,等價于"Max-Age: 0" // MaxAge>0表示存在Max-Age屬性,單位是秒 MaxAge int Secure bool HttpOnly bool Raw string Unparsed []string // 未解析的“屬性-值”對的原始文本 } ``` Cookie代表一個出現在HTTP回復的頭域中Set-Cookie頭的值里或者HTTP請求的頭域中Cookie頭的值里的HTTP cookie。 ### func (\*Cookie) [String](https://github.com/golang/go/blob/master/src/net/http/cookie.go#L136 "View Source") ``` func (c *Cookie) String() string ``` String返回該cookie的序列化結果。如果只設置了Name和Value字段,序列化結果可用于HTTP請求的Cookie頭或者HTTP回復的Set-Cookie頭;如果設置了其他字段,序列化結果只能用于HTTP回復的Set-Cookie頭。 ## type [CookieJar](https://github.com/golang/go/blob/master/src/net/http/jar.go#L17 "View Source") ``` type CookieJar interface { // SetCookies管理從u的回復中收到的cookie // 根據其策略和實現,它可以選擇是否存儲cookie SetCookies(u *url.URL, cookies []*Cookie) // Cookies返回發送請求到u時應使用的cookie // 本方法有責任遵守RFC 6265規定的標準cookie限制 Cookies(u *url.URL) []*Cookie } ``` CookieJar管理cookie的存儲和在HTTP請求中的使用。CookieJar的實現必須能安全的被多個go程同時使用。 net/http/cookiejar包提供了一個CookieJar的實現。 ## type [Request](https://github.com/golang/go/blob/master/src/net/http/request.go#L76 "View Source") ``` type Request struct { // Method指定HTTP方法(GET、POST、PUT等)。對客戶端,""代表GET。 Method string // URL在服務端表示被請求的URI,在客戶端表示要訪問的URL。 // // 在服務端,URL字段是解析請求行的URI(保存在RequestURI字段)得到的, // 對大多數請求來說,除了Path和RawQuery之外的字段都是空字符串。 // (參見RFC 2616, Section 5.1.2) // // 在客戶端,URL的Host字段指定了要連接的服務器, // 而Request的Host字段(可選地)指定要發送的HTTP請求的Host頭的值。 URL *url.URL // 接收到的請求的協議版本。本包生產的Request總是使用HTTP/1.1 Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 // Header字段用來表示HTTP請求的頭域。如果頭域(多行鍵值對格式)為: // accept-encoding: gzip, deflate // Accept-Language: en-us // Connection: keep-alive // 則: // Header = map[string][]string{ // "Accept-Encoding": {"gzip, deflate"}, // "Accept-Language": {"en-us"}, // "Connection": {"keep-alive"}, // } // HTTP規定頭域的鍵名(頭名)是大小寫敏感的,請求的解析器通過規范化頭域的鍵名來實現這點。 // 在客戶端的請求,可能會被自動添加或重寫Header中的特定的頭,參見Request.Write方法。 Header Header // Body是請求的主體。 // // 在客戶端,如果Body是nil表示該請求沒有主體買入GET請求。 // Client的Transport字段會負責調用Body的Close方法。 // // 在服務端,Body字段總是非nil的;但在沒有主體時,讀取Body會立刻返回EOF。 // Server會關閉請求的主體,ServeHTTP處理器不需要關閉Body字段。 Body io.ReadCloser // ContentLength記錄相關內容的長度。 // 如果為-1,表示長度未知,如果>=0,表示可以從Body字段讀取ContentLength字節數據。 // 在客戶端,如果Body非nil而該字段為0,表示不知道Body的長度。 ContentLength int64 // TransferEncoding按從最外到最里的順序列出傳輸編碼,空切片表示"identity"編碼。 // 本字段一般會被忽略。當發送或接受請求時,會自動添加或移除"chunked"傳輸編碼。 TransferEncoding []string // Close在服務端指定是否在回復請求后關閉連接,在客戶端指定是否在發送請求后關閉連接。 Close bool // 在服務端,Host指定URL會在其上尋找資源的主機。 // 根據RFC 2616,該值可以是Host頭的值,或者URL自身提供的主機名。 // Host的格式可以是"host:port"。 // // 在客戶端,請求的Host字段(可選地)用來重寫請求的Host頭。 // 如過該字段為"",Request.Write方法會使用URL字段的Host。 Host string // Form是解析好的表單數據,包括URL字段的query參數和POST或PUT的表單數據。 // 本字段只有在調用ParseForm后才有效。在客戶端,會忽略請求中的本字段而使用Body替代。 Form url.Values // PostForm是解析好的POST或PUT的表單數據。 // 本字段只有在調用ParseForm后才有效。在客戶端,會忽略請求中的本字段而使用Body替代。 PostForm url.Values // MultipartForm是解析好的多部件表單,包括上傳的文件。 // 本字段只有在調用ParseMultipartForm后才有效。 // 在客戶端,會忽略請求中的本字段而使用Body替代。 MultipartForm *multipart.Form // Trailer指定了會在請求主體之后發送的額外的頭域。 // // 在服務端,Trailer字段必須初始化為只有trailer鍵,所有鍵都對應nil值。 // (客戶端會聲明哪些trailer會發送) // 在處理器從Body讀取時,不能使用本字段。 // 在從Body的讀取返回EOF后,Trailer字段會被更新完畢并包含非nil的值。 // (如果客戶端發送了這些鍵值對),此時才可以訪問本字段。 // // 在客戶端,Trail必須初始化為一個包含將要發送的鍵值對的映射。(值可以是nil或其終值) // ContentLength字段必須是0或-1,以啟用"chunked"傳輸編碼發送請求。 // 在開始發送請求后,Trailer可以在讀取請求主體期間被修改, // 一旦請求主體返回EOF,調用者就不可再修改Trailer。 // // 很少有HTTP客戶端、服務端或代理支持HTTP trailer。 Trailer Header // RemoteAddr允許HTTP服務器和其他軟件記錄該請求的來源地址,一般用于日志。 // 本字段不是ReadRequest函數填寫的,也沒有定義格式。 // 本包的HTTP服務器會在調用處理器之前設置RemoteAddr為"IP:port"格式的地址。 // 客戶端會忽略請求中的RemoteAddr字段。 RemoteAddr string // RequestURI是被客戶端發送到服務端的請求的請求行中未修改的請求URI // (參見RFC 2616, Section 5.1) // 一般應使用URI字段,在客戶端設置請求的本字段會導致錯誤。 RequestURI string // TLS字段允許HTTP服務器和其他軟件記錄接收到該請求的TLS連接的信息 // 本字段不是ReadRequest函數填寫的。 // 對啟用了TLS的連接,本包的HTTP服務器會在調用處理器之前設置TLS字段,否則將設TLS為nil。 // 客戶端會忽略請求中的TLS字段。 TLS *tls.ConnectionState } ``` Request類型代表一個服務端接受到的或者客戶端發送出去的HTTP請求。 Request各字段的意義和用途在服務端和客戶端是不同的。除了字段本身上方文檔,還可參見Request.Write方法和RoundTripper接口的文檔。 ### func [NewRequest](https://github.com/golang/go/blob/master/src/net/http/request.go#L479 "View Source") ``` func NewRequest(method, urlStr string, body io.Reader) (*Request, error) ``` NewRequest使用指定的方法、網址和可選的主題創建并返回一個新的\*Request。 如果body參數實現了io.Closer接口,Request返回值的Body?字段會被設置為body,并會被Client類型的Do、Post和PostFOrm方法以及Transport.RoundTrip方法關閉。 ### func [ReadRequest](https://github.com/golang/go/blob/master/src/net/http/request.go#L549 "View Source") ``` func ReadRequest(b *bufio.Reader) (req *Request, err error) ``` ReadRequest從b讀取并解析出一個HTTP請求。(本函數主要用在服務端從下層獲取請求) ### func (\*Request) [ProtoAtLeast](https://github.com/golang/go/blob/master/src/net/http/request.go#L232 "View Source") ``` func (r *Request) ProtoAtLeast(major, minor int) bool ``` ProtoAtLeast報告該請求使用的HTTP協議版本至少是major.minor。 ### func (\*Request) [UserAgent](https://github.com/golang/go/blob/master/src/net/http/request.go#L238 "View Source") ``` func (r *Request) UserAgent() string ``` UserAgent返回請求中的客戶端用戶代理信息(請求的User-Agent頭)。 ### func (\*Request) [Referer](https://github.com/golang/go/blob/master/src/net/http/request.go#L279 "View Source") ``` func (r *Request) Referer() string ``` Referer返回請求中的訪問來路信息。(請求的Referer頭) Referer在請求中就是拼錯了的,這是HTTP早期就有的錯誤。該值也可以從用Header["Referer"]獲取;?讓獲取Referer字段變成方法的好處是,編譯器可以診斷使用正確單詞拼法的req.Referrer()的程序,但卻不能診斷使用Header["Referrer"]的程序。 ### func (\*Request) [AddCookie](https://github.com/golang/go/blob/master/src/net/http/request.go#L262 "View Source") ``` func (r *Request) AddCookie(c *Cookie) ``` AddCookie向請求中添加一個cookie。按照[RFC 6265](http://tools.ietf.org/html/rfc6265)?section 5.4的跪地,AddCookie不會添加超過一個Cookie頭字段。這表示所有的cookie都寫在同一行,用分號分隔(cookie內部用逗號分隔屬性)。 ### func (\*Request) [SetBasicAuth](https://github.com/golang/go/blob/master/src/net/http/request.go#L517 "View Source") ``` func (r *Request) SetBasicAuth(username, password string) ``` SetBasicAuth使用提供的用戶名和密碼,采用HTTP基本認證,設置請求的Authorization頭。HTTP基本認證會明碼傳送用戶名和密碼。 ### func (\*Request) [Write](https://github.com/golang/go/blob/master/src/net/http/request.go#L350 "View Source") ``` func (r *Request) Write(w io.Writer) error ``` Write方法以有線格式將HTTP/1.1請求寫入w(用于將請求寫入下層TCPConn等)。本方法會考慮請求的如下字段: ``` Host URL Method (defaults to "GET") Header ContentLength TransferEncoding Body ``` 如果存在Body,ContentLength字段&lt;= 0且TransferEncoding字段未顯式設置為["identity"],Write方法會顯式添加"Transfer-Encoding: chunked"到請求的頭域。Body字段會在發送完請求后關閉。 ### func (\*Request) [WriteProxy](https://github.com/golang/go/blob/master/src/net/http/request.go#L360 "View Source") ``` func (r *Request) WriteProxy(w io.Writer) error ``` WriteProxy類似Write但會將請求以HTTP代理期望的格式發送。 尤其是,按照[RFC 2616](http://tools.ietf.org/html/rfc2616)?Section 5.1.2,WriteProxy會使用絕對URI(包括協議和主機名)來初始化請求的第1行(Request-URI行)。無論何種情況,WriteProxy都會使用r.Host或r.URL.Host設置Host頭。 ### func (\*Request) [Cookies](https://github.com/golang/go/blob/master/src/net/http/request.go#L243 "View Source") ``` func (r *Request) Cookies() []*Cookie ``` Cookies解析并返回該請求的Cookie頭設置的cookie。 ### func (\*Request) [Cookie](https://github.com/golang/go/blob/master/src/net/http/request.go#L251 "View Source") ``` func (r *Request) Cookie(name string) (*Cookie, error) ``` Cookie返回請求中名為name的cookie,如果未找到該cookie會返回nil, ErrNoCookie。 ### func (\*Request) [ParseForm](https://github.com/golang/go/blob/master/src/net/http/request.go#L736 "View Source") ``` func (r *Request) ParseForm() error ``` ParseForm解析URL中的查詢字符串,并將解析結果更新到r.Form字段。 對于POST或PUT請求,ParseForm還會將body當作表單解析,并將結果既更新到r.PostForm也更新到r.Form。解析結果中,POST或PUT請求主體要優先于URL查詢字符串(同名變量,主體的值在查詢字符串的值前面)。 如果請求的主體的大小沒有被MaxBytesReader函數設定限制,其大小默認限制為開頭10MB。 ParseMultipartForm會自動調用ParseForm。重復調用本方法是無意義的。 ### func (\*Request) [ParseMultipartForm](https://github.com/golang/go/blob/master/src/net/http/request.go#L777 "View Source") ``` func (r *Request) ParseMultipartForm(maxMemory int64) error ``` ParseMultipartForm將請求的主體作為multipart/form-data解析。請求的整個主體都會被解析,得到的文件記錄最多maxMemery字節保存在內存,其余部分保存在硬盤的temp文件里。如果必要,ParseMultipartForm會自行調用ParseForm。重復調用本方法是無意義的。 ### func (\*Request) [FormValue](https://github.com/golang/go/blob/master/src/net/http/request.go#L812 "View Source") ``` func (r *Request) FormValue(key string) string ``` FormValue返回key為鍵查詢r.Form字段得到結果[]string切片的第一個值。POST和PUT主體中的同名參數優先于URL查詢字符串。如果必要,本函數會隱式調用ParseMultipartForm和ParseForm。 ### func (\*Request) [PostFormValue](https://github.com/golang/go/blob/master/src/net/http/request.go#L825 "View Source") ``` func (r *Request) PostFormValue(key string) string ``` PostFormValue返回key為鍵查詢r.PostForm字段得到結果[]string切片的第一個值。如果必要,本函數會隱式調用ParseMultipartForm和ParseForm。 ### func (\*Request) [FormFile](https://github.com/golang/go/blob/master/src/net/http/request.go#L837 "View Source") ``` func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) ``` FormFile返回以key為鍵查詢r.MultipartForm字段得到結果中的第一個文件和它的信息。如果必要,本函數會隱式調用ParseMultipartForm和ParseForm。查詢失敗會返回ErrMissingFile錯誤。 ### func (\*Request) [MultipartReader](https://github.com/golang/go/blob/master/src/net/http/request.go#L295 "View Source") ``` func (r *Request) MultipartReader() (*multipart.Reader, error) ``` 如果請求是multipart/form-data POST請求,MultipartReader返回一個multipart.Reader接口,否則返回nil和一個錯誤。使用本函數代替ParseMultipartForm,可以將r.Body作為流處理。 ## type [Response](https://github.com/golang/go/blob/master/src/net/http/response.go#L29 "View Source") ``` type Response struct { Status string // 例如"200 OK" StatusCode int // 例如200 Proto string // 例如"HTTP/1.0" ProtoMajor int // 例如1 ProtoMinor int // 例如0 // Header保管頭域的鍵值對。 // 如果回復中有多個頭的鍵相同,Header中保存為該鍵對應用逗號分隔串聯起來的這些頭的值 // (參見RFC 2616 Section 4.2) // 被本結構體中的其他字段復制保管的頭(如ContentLength)會從Header中刪掉。 // // Header中的鍵都是規范化的,參見CanonicalHeaderKey函數 Header Header // Body代表回復的主體。 // Client類型和Transport類型會保證Body字段總是非nil的,即使回復沒有主體或主體長度為0。 // 關閉主體是調用者的責任。 // 如果服務端采用"chunked"傳輸編碼發送的回復,Body字段會自動進行解碼。 Body io.ReadCloser // ContentLength記錄相關內容的長度。 // 其值為-1表示長度未知(采用chunked傳輸編碼) // 除非對應的Request.Method是"HEAD",其值>=0表示可以從Body讀取的字節數 ContentLength int64 // TransferEncoding按從最外到最里的順序列出傳輸編碼,空切片表示"identity"編碼。 TransferEncoding []string // Close記錄頭域是否指定應在讀取完主體后關閉連接。(即Connection頭) // 該值是給客戶端的建議,Response.Write方法的ReadResponse函數都不會關閉連接。 Close bool // Trailer字段保存和頭域相同格式的trailer鍵值對,和Header字段相同類型 Trailer Header // Request是用來獲取此回復的請求 // Request的Body字段是nil(因為已經被用掉了) // 這個字段是被Client類型發出請求并獲得回復后填充的 Request *Request // TLS包含接收到該回復的TLS連接的信息。?對未加密的回復,本字段為nil。 // 返回的指針是被(同一TLS連接接收到的)回復共享的,不應被修改。 TLS *tls.ConnectionState } ``` Response代表一個HTTP請求的回復。 ### func [ReadResponse](https://github.com/golang/go/blob/master/src/net/http/response.go#L116 "View Source") ``` func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) ``` ReadResponse從r讀取并返回一個HTTP?回復。req參數是可選的,指定該回復對應的請求(即是對該請求的回復)。如果是nil,將假設請求是GET請求。客戶端必須在結束resp.Body的讀取后關閉它。讀取完畢并關閉后,客戶端可以檢查resp.Trailer字段獲取回復的trailer的鍵值對。(本函數主要用在客戶端從下層獲取回復) ### func (\*Response) [ProtoAtLeast](https://github.com/golang/go/blob/master/src/net/http/response.go#L184 "View Source") ``` func (r *Response) ProtoAtLeast(major, minor int) bool ``` ProtoAtLeast報告該回復使用的HTTP協議版本至少是major.minor。 ### func (\*Response) [Cookies](https://github.com/golang/go/blob/master/src/net/http/response.go#L89 "View Source") ``` func (r *Response) Cookies() []*Cookie ``` Cookies解析并返回該回復中的Set-Cookie頭設置的cookie。 ### func (\*Response) [Location](https://github.com/golang/go/blob/master/src/net/http/response.go#L99 "View Source") ``` func (r *Response) Location() (*url.URL, error) ``` Location返回該回復的Location頭設置的URL。相對地址的重定向會相對于該回復對應的請求來確定絕對地址。如果回復中沒有Location頭,會返回nil, ErrNoLocation。 ### func (\*Response) [Write](https://github.com/golang/go/blob/master/src/net/http/response.go#L203 "View Source") ``` func (r *Response) Write(w io.Writer) error ``` Write以有線格式將回復寫入w(用于將回復寫入下層TCPConn等)。本方法會考慮如下字段: ``` StatusCode ProtoMajor ProtoMinor Request.Method TransferEncoding Trailer Body ContentLength Header(不規范的鍵名和它對應的值會導致不可預知的行為) ``` Body字段在發送完回復后會被關閉。 ## type [ResponseWriter](https://github.com/golang/go/blob/master/src/net/http/server.go#L51 "View Source") ``` type ResponseWriter interface { // Header返回一個Header類型值,該值會被WriteHeader方法發送。 // 在調用WriteHeader或Write方法后再改變該對象是沒有意義的。 Header() Header // WriteHeader該方法發送HTTP回復的頭域和狀態碼。 // 如果沒有被顯式調用,第一次調用Write時會觸發隱式調用WriteHeader(http.StatusOK) // WriterHeader的顯式調用主要用于發送錯誤碼。 WriteHeader(int) // Write向連接中寫入作為HTTP的一部分回復的數據。 // 如果被調用時還未調用WriteHeader,本方法會先調用WriteHeader(http.StatusOK) // 如果Header中沒有"Content-Type"鍵, // 本方法會使用包函數DetectContentType檢查數據的前512字節,將返回值作為該鍵的值。 Write([]byte) (int, error) } ``` ResponseWriter接口被HTTP處理器用于構造HTTP回復。 ## type [Flusher](https://github.com/golang/go/blob/master/src/net/http/server.go#L79 "View Source") ``` type Flusher interface { // Flush將緩沖中的所有數據發送到客戶端 Flush() } ``` HTTP處理器ResponseWriter接口參數的下層如果實現了Flusher接口,可以讓HTTP處理器將緩沖中的數據發送到客戶端。 注意:即使ResponseWriter接口的下層支持Flush方法,如果客戶端是通過HTTP代理連接的,緩沖中的數據也可能直到回復完畢才被傳輸到客戶端。 ## type [CloseNotifier](https://github.com/golang/go/blob/master/src/net/http/server.go#L100 "View Source") ``` type CloseNotifier interface { // CloseNotify返回一個通道,該通道會在客戶端連接丟失時接收到唯一的值 CloseNotify() <-chan bool } ``` HTTP處理器ResponseWriter接口參數的下層如果實現了CloseNotifier接口,可以讓用戶檢測下層的連接是否停止。如果客戶端在回復準備好之前關閉了連接,該機制可以用于取消服務端耗時較長的操作。 ## type [Hijacker](https://github.com/golang/go/blob/master/src/net/http/server.go#L86 "View Source") ``` type Hijacker interface { // Hijack讓調用者接管連接,返回連接和關聯到該連接的一個緩沖讀寫器。 // 調用本方法后,HTTP服務端將不再對連接進行任何操作, // 調用者有責任管理、關閉返回的連接。 Hijack() (net.Conn, *bufio.ReadWriter, error) } ``` HTTP處理器ResponseWriter接口參數的下層如果實現了Hijacker接口,可以讓HTTP處理器接管該連接。 Example ``` http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) { hj, ok := w.(http.Hijacker) if !ok { http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError) return } conn, bufrw, err := hj.Hijack() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Don't forget to close the connection: defer conn.Close() bufrw.WriteString("Now we're speaking raw TCP. Say hi: ") bufrw.Flush() s, err := bufrw.ReadString('\n') if err != nil { log.Printf("error reading string: %v", err) return } fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s) bufrw.Flush() }) ``` ## type [RoundTripper](https://github.com/golang/go/blob/master/src/net/http/client.go#L82 "View Source") ``` type RoundTripper interface { // RoundTrip執行單次HTTP事務,接收并發揮請求req的回復。 // RoundTrip不應試圖解析/修改得到的回復。 // 尤其要注意,只要RoundTrip獲得了一個回復,不管該回復的HTTP狀態碼如何, // 它必須將返回值err設置為nil。 // 非nil的返回值err應該留給獲取回復失敗的情況。 // 類似的,RoundTrip不能試圖管理高層次的細節,如重定向、認證、cookie。 // // 除了從請求的主體讀取并關閉主體之外,RoundTrip不應修改請求,包括(請求的)錯誤。 // RoundTrip函數接收的請求的URL和Header字段可以保證是(被)初始化了的。 RoundTrip(*Request) (*Response, error) } ``` RoundTripper接口是具有執行單次HTTP事務的能力(接收指定請求的回復)的接口。 RoundTripper接口的類型必須可以安全的被多線程同時使用。 ## type [Transport](https://github.com/golang/go/blob/master/src/net/http/transport.go#L49 "View Source") ``` type Transport struct { // Proxy指定一個對給定請求返回代理的函數。 // 如果該函數返回了非nil的錯誤值,請求的執行就會中斷并返回該錯誤。 // 如果Proxy為nil或返回nil的*URL置,將不使用代理。 Proxy func(*Request) (*url.URL, error) // Dial指定創建TCP連接的撥號函數。如果Dial為nil,會使用net.Dial。 Dial func(network, addr string) (net.Conn, error) // TLSClientConfig指定用于tls.Client的TLS配置信息。 // 如果該字段為nil,會使用默認的配置信息。 TLSClientConfig *tls.Config // TLSHandshakeTimeout指定等待TLS握手完成的最長時間。零值表示不設置超時。 TLSHandshakeTimeout time.Duration // 如果DisableKeepAlives為真,會禁止不同HTTP請求之間TCP連接的重用。 DisableKeepAlives bool // 如果DisableCompression為真,會禁止Transport在請求中沒有Accept-Encoding頭時, // 主動添加"Accept-Encoding: gzip"頭,以獲取壓縮數據。 // 如果Transport自己請求gzip并得到了壓縮后的回復,它會主動解壓縮回復的主體。 // 但如果用戶顯式的請求gzip壓縮數據,Transport是不會主動解壓縮的。 DisableCompression bool // 如果MaxIdleConnsPerHost!=0,會控制每個主機下的最大閑置連接。 // 如果MaxIdleConnsPerHost==0,會使用DefaultMaxIdleConnsPerHost。 MaxIdleConnsPerHost int // ResponseHeaderTimeout指定在發送完請求(包括其可能的主體)之后, // 等待接收服務端的回復的頭域的最大時間。零值表示不設置超時。 // 該時間不包括獲取回復主體的時間。 ResponseHeaderTimeout time.Duration // 內含隱藏或非導出字段 } ``` Transport類型實現了RoundTripper接口,支持http、https和http/https代理。Transport類型可以緩存連接以在未來重用。 ``` var DefaultTransport RoundTripper = &Transport{ Proxy: ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 10 * time.Second, } ``` DefaultTransport是被包變量DefaultClient使用的默認RoundTripper接口。它會根據需要創建網絡連接,并緩存以便在之后的請求中重用這些連接。它使用環境變量$HTTP_PROXY和$NO_PROXY(或$http_proxy和$no_proxy)指定的HTTP代理。 ### func (\*Transport) [RegisterProtocol](https://github.com/golang/go/blob/master/src/net/http/transport.go#L217 "View Source") ``` func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) ``` RegisterProtocol注冊一個新的名為scheme的協議。t會將使用scheme協議的請求轉交給rt。rt有責任模擬HTTP請求的語義。 RegisterProtocol可以被其他包用于提供"ftp"或"file"等協議的實現。 ### func (\*Transport) [RoundTrip](https://github.com/golang/go/blob/master/src/net/http/transport.go#L164 "View Source") ``` func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) ``` RoundTrip方法實現了RoundTripper接口。 高層次的HTTP客戶端支持(如管理cookie和重定向)請參見Get、Post等函數和Client類型。 ### func (\*Transport) [CloseIdleConnections](https://github.com/golang/go/blob/master/src/net/http/transport.go#L236 "View Source") ``` func (t *Transport) CloseIdleConnections() ``` CloseIdleConnections關閉所有之前的請求建立但目前處于閑置狀態的連接。本方法不會中斷正在使用的連接。 ### func (\*Transport) [CancelRequest](https://github.com/golang/go/blob/master/src/net/http/transport.go#L251 "View Source") ``` func (t *Transport) CancelRequest(req *Request) ``` CancelRequest通過關閉請求所在的連接取消一個執行中的請求。 ## type [Client](https://github.com/golang/go/blob/master/src/net/http/client.go#L35 "View Source") ``` type Client struct { // Transport指定執行獨立、單次HTTP請求的機制。 // 如果Transport為nil,則使用DefaultTransport。 Transport RoundTripper // CheckRedirect指定處理重定向的策略。 // 如果CheckRedirect不為nil,客戶端會在執行重定向之前調用本函數字段。 // 參數req和via是將要執行的請求和已經執行的請求(切片,越新的請求越靠后)。 // 如果CheckRedirect返回一個錯誤,本類型的Get方法不會發送請求req, // 而是返回之前得到的最后一個回復和該錯誤。(包裝進url.Error類型里) // // 如果CheckRedirect為nil,會采用默認策略:連續10此請求后停止。 CheckRedirect func(req *Request, via []*Request) error // Jar指定cookie管理器。 // 如果Jar為nil,請求中不會發送cookie,回復中的cookie會被忽略。 Jar CookieJar // Timeout指定本類型的值執行請求的時間限制。 // 該超時限制包括連接時間、重定向和讀取回復主體的時間。 // 計時器會在Head、Get、Post或Do方法返回后繼續運作并在超時后中斷回復主體的讀取。 // // Timeout為零值表示不設置超時。 // // Client實例的Transport字段必須支持CancelRequest方法, // 否則Client會在試圖用Head、Get、Post或Do方法執行請求時返回錯誤。 // 本類型的Transport字段默認值(DefaultTransport)支持CancelRequest方法。 Timeout time.Duration } ``` Client類型代表HTTP客戶端。它的零值(DefaultClient)是一個可用的使用DefaultTransport的客戶端。 Client的Transport字段一般會含有內部狀態(緩存TCP連接),因此Client類型值應盡量被重用而不是每次需要都創建新的。Client類型值可以安全的被多個go程同時使用。 Client類型的層次比RoundTripper接口(如Transport)高,還會管理HTTP的cookie和重定向等細節。 ### func (\*Client) [Do](https://github.com/golang/go/blob/master/src/net/http/client.go#L148 "View Source") ``` func (c *Client) Do(req *Request) (resp *Response, err error) ``` Do方法發送請求,返回HTTP回復。它會遵守客戶端c設置的策略(如重定向、cookie、認證)。 如果客戶端的策略(如重定向)返回錯誤或存在HTTP協議錯誤時,本方法將返回該錯誤;如果回應的狀態碼不是2xx,本方法并不會返回錯誤。 如果返回值err為nil,resp.Body總是非nil的,調用者應該在讀取完resp.Body后關閉它。如果返回值resp的主體未關閉,c下層的RoundTripper接口(一般為Transport類型)可能無法重用resp主體下層保持的TCP連接去執行之后的請求。 請求的主體,如果非nil,會在執行后被c.Transport關閉,即使出現錯誤。 一般應使用Get、Post或PostForm方法代替Do方法。 ### func (\*Client) [Head](https://github.com/golang/go/blob/master/src/net/http/client.go#L462 "View Source") ``` func (c *Client) Head(url string) (resp *Response, err error) ``` Head向指定的URL發出一個HEAD請求,如果回應的狀態碼如下,Head會在調用c.CheckRedirect后執行重定向: ``` 301 (Moved Permanently) 302 (Found) 303 (See Other) 307 (Temporary Redirect) ``` ### func (\*Client) [Get](https://github.com/golang/go/blob/master/src/net/http/client.go#L270 "View Source") ``` func (c *Client) Get(url string) (resp *Response, err error) ``` Get向指定的URL發出一個GET請求,如果回應的狀態碼如下,Get會在調用c.CheckRedirect后執行重定向: ``` 301 (Moved Permanently) 302 (Found) 303 (See Other) 307 (Temporary Redirect) ``` 如果c.CheckRedirect執行失敗或存在HTTP協議錯誤時,本方法將返回該錯誤;如果回應的狀態碼不是2xx,本方法并不會返回錯誤。如果返回值err為nil,resp.Body總是非nil的,調用者應該在讀取完resp.Body后關閉它。 ### func (\*Client) [Post](https://github.com/golang/go/blob/master/src/net/http/client.go#L411 "View Source") ``` func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) ``` Post向指定的URL發出一個POST請求。bodyType為POST數據的類型,?body為POST數據,作為請求的主體。如果參數body實現了io.Closer接口,它會在發送請求后被關閉。調用者有責任在讀取完返回值resp的主體后關閉它。 ### func (\*Client) [PostForm](https://github.com/golang/go/blob/master/src/net/http/client.go#L436 "View Source") ``` func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) ``` PostForm向指定的URL發出一個POST請求,url.Values類型的data會被編碼為請求的主體。POST數據的類型一般會設為"application/x-www-form-urlencoded"。如果返回值err為nil,resp.Body總是非nil的,調用者應該在讀取完resp.Body后關閉它。 ## type [Handler](https://github.com/golang/go/blob/master/src/net/http/server.go#L45 "View Source") ``` type Handler interface { ServeHTTP(ResponseWriter, *Request) } ``` 實現了Handler接口的對象可以注冊到HTTP服務端,為特定的路徑及其子樹提供服務。 ServeHTTP應該將回復的頭域和數據寫入ResponseWriter接口然后返回。返回標志著該請求已經結束,HTTP服務端可以轉移向該連接上的下一個請求。 ### func [NotFoundHandler](https://github.com/golang/go/blob/master/src/net/http/server.go#L1253 "View Source") ``` func NotFoundHandler() Handler ``` NotFoundHandler返回一個簡單的請求處理器,該處理器會對每個請求都回復"404 page not found"。 ### func [RedirectHandler](https://github.com/golang/go/blob/master/src/net/http/server.go#L1360 "View Source") ``` func RedirectHandler(url string, code int) Handler ``` RedirectHandler返回一個請求處理器,該處理器會對每個請求都使用狀態碼code重定向到網址url。 ### func [TimeoutHandler](https://github.com/golang/go/blob/master/src/net/http/server.go#L1860 "View Source") ``` func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler ``` TimeoutHandler返回一個采用指定時間限制的請求處理器。 返回的Handler會調用h.ServeHTTP去處理每個請求,但如果某一次調用耗時超過了時間限制,該處理器會回復請求狀態碼503 Service Unavailable,并將msg作為回復的主體(如果msg為空字符串,將發送一個合理的默認信息)。在超時后,h對它的ResponseWriter接口參數的寫入操作會返回ErrHandlerTimeout。 ### func [StripPrefix](https://github.com/golang/go/blob/master/src/net/http/server.go#L1260 "View Source") ``` func StripPrefix(prefix string, h Handler) Handler ``` StripPrefix返回一個處理器,該處理器會將請求的URL.Path字段中給定前綴prefix去除后再交由h處理。StripPrefix會向URL.Path字段中沒有給定前綴的請求回復404 page not found。 Example ``` // To serve a directory on disk (/tmp) under an alternate URL // path (/tmpfiles/), use StripPrefix to modify the request // URL's path before the FileServer sees it: http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))) ``` ## type [HandlerFunc](https://github.com/golang/go/blob/master/src/net/http/server.go#L1231 "View Source") ``` type HandlerFunc func(ResponseWriter, *Request) ``` HandlerFunc type是一個適配器,通過類型轉換讓我們可以將普通的函數作為HTTP處理器使用。如果f是一個具有適當簽名的函數,HandlerFunc(f)通過調用f實現了Handler接口。 ### func (HandlerFunc) [ServeHTTP](https://github.com/golang/go/blob/master/src/net/http/server.go#L1234 "View Source") ``` func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) ``` ServeHTTP方法會調用f(w, r) ## type [ServeMux](https://github.com/golang/go/blob/master/src/net/http/server.go#L1391 "View Source") ``` type ServeMux struct { // 內含隱藏或非導出字段 } ``` ServeMux類型是HTTP請求的多路轉接器。它會將每一個接收的請求的URL與一個注冊模式的列表進行匹配,并調用和URL最匹配的模式的處理器。 模式是固定的、由根開始的路徑,如"/favicon.ico",或由根開始的子樹,如"/images/"(注意結尾的斜杠)。較長的模式優先于較短的模式,因此如果模式"/images/"和"/images/thumbnails/"都注冊了處理器,后一個處理器會用于路徑以"/images/thumbnails/"開始的請求,前一個處理器會接收到其余的路徑在"/images/"子樹下的請求。 注意,因為以斜杠結尾的模式代表一個由根開始的子樹,模式"/"會匹配所有的未被其他注冊的模式匹配的路徑,而不僅僅是路徑"/"。 模式也能(可選地)以主機名開始,表示只匹配該主機上的路徑。指定主機的模式優先于一般的模式,因此一個注冊了兩個模式"/codesearch"和"codesearch.google.com/"的處理器不會接管目標為"[http://www.google.com/](http://www.google.com/)"的請求。 ServeMux還會注意到請求的URL路徑的無害化,將任何路徑中包含"."或".."元素的請求重定向到等價的沒有這兩種元素的URL。(參見path.Clean函數) ### func [NewServeMux](https://github.com/golang/go/blob/master/src/net/http/server.go#L1404 "View Source") ``` func NewServeMux() *ServeMux ``` NewServeMux創建并返回一個新的\*ServeMux ### func (\*ServeMux) [Handle](https://github.com/golang/go/blob/master/src/net/http/server.go#L1516 "View Source") ``` func (mux *ServeMux) Handle(pattern string, handler Handler) ``` Handle注冊HTTP處理器handler和對應的模式pattern。如果該模式已經注冊有一個處理器,Handle會panic。 Example ``` mux := http.NewServeMux() mux.Handle("/api/", apiHandler{}) mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { // The "/" pattern matches everything, so we need to check // that we're at the root here. if req.URL.Path != "/" { http.NotFound(w, req) return } fmt.Fprintf(w, "Welcome to the home page!") }) ``` ### func (\*ServeMux) [HandleFunc](https://github.com/golang/go/blob/master/src/net/http/server.go#L1554 "View Source") ``` func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) ``` HandleFunc注冊一個處理器函數handler和對應的模式pattern。 ### func (\*ServeMux) [Handler](https://github.com/golang/go/blob/master/src/net/http/server.go#L1468 "View Source") ``` func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) ``` Handler根據r.Method、r.Host和r.URL.Path等數據,返回將用于處理該請求的HTTP處理器。它總是返回一個非nil的處理器。如果路徑不是它的規范格式,將返回內建的用于重定向到等價的規范路徑的處理器。 Handler也會返回匹配該請求的的已注冊模式;在內建重定向處理器的情況下,pattern會在重定向后進行匹配。如果沒有已注冊模式可以應用于該請求,本方法將返回一個內建的"404 page not found"處理器和一個空字符串模式。 ### func (\*ServeMux) [ServeHTTP](https://github.com/golang/go/blob/master/src/net/http/server.go#L1502 "View Source") ``` func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) ``` ServeHTTP將請求派遣到與請求的URL最匹配的模式對應的處理器。 ## type [Server](https://github.com/golang/go/blob/master/src/net/http/server.go#L1581 "View Source") ``` type Server struct { Addr string // 監聽的TCP地址,如果為空字符串會使用":http" Handler Handler // 調用的處理器,如為nil會調用http.DefaultServeMux ReadTimeout time.Duration // 請求的讀取操作在超時前的最大持續時間 WriteTimeout time.Duration // 回復的寫入操作在超時前的最大持續時間 MaxHeaderBytes int // 請求的頭域最大長度,如為0則用DefaultMaxHeaderBytes TLSConfig *tls.Config // 可選的TLS配置,用于ListenAndServeTLS方法 // TLSNextProto(可選地)指定一個函數來在一個NPN型協議升級出現時接管TLS連接的所有權。 // 映射的鍵為商談的協議名;映射的值為函數,該函數的Handler參數應處理HTTP請求, // 并且初始化Handler.ServeHTTP的*Request參數的TLS和RemoteAddr字段(如果未設置)。 // 連接在函數返回時會自動關閉。 TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // ConnState字段指定一個可選的回調函數,該函數會在一個與客戶端的連接改變狀態時被調用。 // 參見ConnState類型和相關常數獲取細節。 ConnState func(net.Conn, ConnState) // ErrorLog指定一個可選的日志記錄器,用于記錄接收連接時的錯誤和處理器不正常的行為。 // 如果本字段為nil,日志會通過log包的標準日志記錄器寫入os.Stderr。 ErrorLog *log.Logger // 內含隱藏或非導出字段 } ``` Server類型定義了運行HTTP服務端的參數。Server的零值是合法的配置。 ### func (\*Server) [SetKeepAlivesEnabled](https://github.com/golang/go/blob/master/src/net/http/server.go#L1733 "View Source") ``` func (s *Server) SetKeepAlivesEnabled(v bool) ``` SetKeepAlivesEnabled控制是否允許HTTP閑置連接重用(keep-alive)功能。默認該功能總是被啟用的。只有資源非常緊張的環境或者服務端在關閉進程中時,才應該關閉該功能。 ### func (\*Server) [Serve](https://github.com/golang/go/blob/master/src/net/http/server.go#L1694 "View Source") ``` func (srv *Server) Serve(l net.Listener) error ``` Serve會接手監聽器l收到的每一個連接,并為每一個連接創建一個新的服務go程。該go程會讀取請求,然后調用srv.Handler回復請求。 ### func (\*Server) [ListenAndServe](https://github.com/golang/go/blob/master/src/net/http/server.go#L1679 "View Source") ``` func (srv *Server) ListenAndServe() error ``` ListenAndServe監聽srv.Addr指定的TCP地址,并且會調用Serve方法接收到的連接。如果srv.Addr為空字符串,會使用":http"。 ### func (\*Server) [ListenAndServeTLS](https://github.com/golang/go/blob/master/src/net/http/server.go#L1823 "View Source") ``` func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error ``` ListenAndServeTLS監聽srv.Addr確定的TCP地址,并且會調用Serve方法處理接收到的連接。必須提供證書文件和對應的私鑰文件。如果證書是由權威機構簽發的,certFile參數必須是順序串聯的服務端證書和CA證書。如果srv.Addr為空字符串,會使用":https"。 ## type [File](https://github.com/golang/go/blob/master/src/net/http/fs.go#L58 "View Source") ``` type File interface { io.Closer io.Reader Readdir(count int) ([]os.FileInfo, error) Seek(offset int64, whence int) (int64, error) Stat() (os.FileInfo, error) } ``` File是被FileSystem接口的Open方法返回的接口類型,可以被FileServer等函數用于文件訪問服務。 該接口的方法的行為應該和\*os.File類型的同名方法相同。 ## type [FileSystem](https://github.com/golang/go/blob/master/src/net/http/fs.go#L50 "View Source") ``` type FileSystem interface { Open(name string) (File, error) } ``` FileSystem接口實現了對一系列命名文件的訪問。文件路徑的分隔符為'/',不管主機操作系統的慣例如何。 ## type [Dir](https://github.com/golang/go/blob/master/src/net/http/fs.go#L29 "View Source") ``` type Dir string ``` Dir使用限制到指定目錄樹的本地文件系統實現了http.FileSystem接口。空Dir被視為".",即代表當前目錄。 ### func (Dir) [Open](https://github.com/golang/go/blob/master/src/net/http/fs.go#L31 "View Source") ``` func (d Dir) Open(name string) (File, error) ``` ## func [NewFileTransport](https://github.com/golang/go/blob/master/src/net/http/filetransport.go#L30 "View Source") ``` func NewFileTransport(fs FileSystem) RoundTripper ``` NewFileTransport返回一個RoundTripper接口,使用FileSystem接口fs提供文件訪問服務。?返回的RoundTripper接口會忽略接收的請求的URL主機及其他絕大多數屬性。 NewFileTransport函數的典型使用情況是給Transport類型的值注冊"file"協議,如下所示: ``` t := &http.Transport{} t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/"))) c := &http.Client{Transport: t} res, err := c.Get("file:///etc/passwd") ... ``` ## func [FileServer](https://github.com/golang/go/blob/master/src/net/http/fs.go#L435 "View Source") ``` func FileServer(root FileSystem) Handler ``` FileServer返回一個使用FileSystem接口root提供文件訪問服務的HTTP處理器。要使用操作系統的FileSystem接口實現,可使用http.Dir: ``` http.Handle("/", http.FileServer(http.Dir("/tmp"))) ``` Example ``` // Simple static webserver: log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc")))) ``` Example (StripPrefix) ``` // To serve a directory on disk (/tmp) under an alternate URL // path (/tmpfiles/), use StripPrefix to modify the request // URL's path before the FileServer sees it: http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))) ``` ## func [ProxyURL](https://github.com/golang/go/blob/master/src/net/http/transport.go#L140 "View Source") ``` func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) ``` ProxyURL返回一個代理函數(用于Transport類型),該函數總是返回同一個URL。 ## func [ProxyFromEnvironment](https://github.com/golang/go/blob/master/src/net/http/transport.go#L115 "View Source") ``` func ProxyFromEnvironment(req *Request) (*url.URL, error) ``` ProxyFromEnvironment使用環境變量$HTTP_PROXY和$NO_PROXY(或$http_proxy和$no_proxy)的配置返回用于req的代理。如果代理環境不合法將返回錯誤;如果環境未設定代理或者給定的request不應使用代理時,將返回(nil, nil);如果req.URL.Host字段是"localhost"(可以有端口號,也可以沒有),也會返回(nil, nil)。 ## func [SetCookie](https://github.com/golang/go/blob/master/src/net/http/cookie.go#L129 "View Source") ``` func SetCookie(w ResponseWriter, cookie *Cookie) ``` SetCookie在w的頭域中添加Set-Cookie頭,該HTTP頭的值為cookie。 ## func [Redirect](https://github.com/golang/go/blob/master/src/net/http/server.go#L1276 "View Source") ``` func Redirect(w ResponseWriter, r *Request, urlStr string, code int) ``` Redirect回復請求一個重定向地址urlStr和狀態碼code。該重定向地址可以是相對于請求r的相對地址。 ## func [NotFound](https://github.com/golang/go/blob/master/src/net/http/server.go#L1249 "View Source") ``` func NotFound(w ResponseWriter, r *Request) ``` NotFound回復請求404狀態碼(not found:目標未發現)。 ## func [Error](https://github.com/golang/go/blob/master/src/net/http/server.go#L1242 "View Source") ``` func Error(w ResponseWriter, error string, code int) ``` Error使用指定的錯誤信息和狀態碼回復請求,將數據寫入w。錯誤信息必須是明文。 ## func [ServeContent](https://github.com/golang/go/blob/master/src/net/http/fs.go#L113 "View Source") ``` func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) ``` ServeContent使用提供的ReadSeeker的內容回復請求。ServeContent比起io.Copy函數的主要優點,是可以處理范圍類請求(只要一部分內容)、設置MIME類型,處理If-Modified-Since請求。 如果未設定回復的Content-Type頭,本函數首先會嘗試從name的文件擴展名推斷數據類型;如果失敗,會用讀取content的第1塊數據并提供給DetectContentType推斷類型;之后會設置Content-Type頭。參數name不會用于別的地方,甚至于它可以是空字符串,也永遠不會發送到回復里。 如果modtime不是Time零值,函數會在回復的頭域里設置Last-Modified頭。如果請求的頭域包含If-Modified-Since頭,本函數會使用modtime參數來確定是否應該發送內容。如果調用者設置了w的ETag頭,ServeContent會使用它處理包含If-Range頭和If-None-Match頭的請求。 參數content的Seek方法必須有效:函數使用Seek來確定它的大小。 注意:本包File接口和\*os.File類型都實現了io.ReadSeeker接口。 ## func [ServeFile](https://github.com/golang/go/blob/master/src/net/http/fs.go#L419 "View Source") ``` func ServeFile(w ResponseWriter, r *Request, name string) ``` ServeFile回復請求name指定的文件或者目錄的內容。 ## func [MaxBytesReader](https://github.com/golang/go/blob/master/src/net/http/request.go#L637 "View Source") ``` func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser ``` MaxBytesReader類似io.LimitReader,但它是用來限制接收到的請求的Body的大小的。不同于io.LimitReader,本函數返回一個ReadCloser,返回值的Read方法在讀取的數據超過大小限制時會返回非EOF錯誤,其Close方法會關閉下層的io.ReadCloser接口r。 MaxBytesReader預防客戶端因為意外或者蓄意發送的“大”請求,以避免尺寸過大的請求浪費服務端資源。 ## func [Head](https://github.com/golang/go/blob/master/src/net/http/client.go#L450 "View Source") ``` func Head(url string) (resp *Response, err error) ``` Head向指定的URL發出一個HEAD請求,如果回應的狀態碼如下,Head會在調用c.CheckRedirect后執行重定向: ``` 301 (Moved Permanently) 302 (Found) 303 (See Other) 307 (Temporary Redirect) ``` Head是對包變量DefaultClient的Head方法的包裝。 ## func [Get](https://github.com/golang/go/blob/master/src/net/http/client.go#L251 "View Source") ``` func Get(url string) (resp *Response, err error) ``` Get向指定的URL發出一個GET請求,如果回應的狀態碼如下,Get會在調用c.CheckRedirect后執行重定向: ``` 301 (Moved Permanently) 302 (Found) 303 (See Other) 307 (Temporary Redirect) ``` 如果c.CheckRedirect執行失敗或存在HTTP協議錯誤時,本方法將返回該錯誤;如果回應的狀態碼不是2xx,本方法并不會返回錯誤。如果返回值err為nil,resp.Body總是非nil的,調用者應該在讀取完resp.Body后關閉它。 Get是對包變量DefaultClient的Get方法的包裝。 Example ``` res, err := http.Get("http://www.google.com/robots.txt") if err != nil { log.Fatal(err) } robots, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Fatal(err) } fmt.Printf("%s", robots) ``` ## func [Post](https://github.com/golang/go/blob/master/src/net/http/client.go#L401 "View Source") ``` func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) ``` Post向指定的URL發出一個POST請求。bodyType為POST數據的類型,?body為POST數據,作為請求的主體。如果參數body實現了io.Closer接口,它會在發送請求后被關閉。調用者有責任在讀取完返回值resp的主體后關閉它。 Post是對包變量DefaultClient的Post方法的包裝。 ## func [PostForm](https://github.com/golang/go/blob/master/src/net/http/client.go#L427 "View Source") ``` func PostForm(url string, data url.Values) (resp *Response, err error) ``` PostForm向指定的URL發出一個POST請求,url.Values類型的data會被編碼為請求的主體。如果返回值err為nil,resp.Body總是非nil的,調用者應該在讀取完resp.Body后關閉它。 PostForm是對包變量DefaultClient的PostForm方法的包裝。 ## func [Handle](https://github.com/golang/go/blob/master/src/net/http/server.go#L1561 "View Source") ``` func Handle(pattern string, handler Handler) ``` Handle注冊HTTP處理器handler和對應的模式pattern(注冊到DefaultServeMux)。如果該模式已經注冊有一個處理器,Handle會panic。ServeMux的文檔解釋了模式的匹配機制。 ## func [HandleFunc](https://github.com/golang/go/blob/master/src/net/http/server.go#L1566 "View Source") ``` func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) ``` HandleFunc注冊一個處理器函數handler和對應的模式pattern(注冊到DefaultServeMux)。ServeMux的文檔解釋了模式的匹配機制。 ## func [Serve](https://github.com/golang/go/blob/master/src/net/http/server.go#L1574 "View Source") ``` func Serve(l net.Listener, handler Handler) error ``` Serve會接手監聽器l收到的每一個連接,并為每一個連接創建一個新的服務go程。該go程會讀取請求,然后調用handler回復請求。handler參數一般會設為nil,此時會使用DefaultServeMux。 ## func [ListenAndServe](https://github.com/golang/go/blob/master/src/net/http/server.go#L1776 "View Source") ``` func ListenAndServe(addr string, handler Handler) error ``` ListenAndServe監聽TCP地址addr,并且會使用handler參數調用Serve函數處理接收到的連接。handler參數一般會設為nil,此時會使用DefaultServeMux。 一個簡單的服務端例子: ``` package main import ( "io" "net/http" "log" ) // hello world, the web server func HelloServer(w http.ResponseWriter, req *http.Request) { io.WriteString(w, "hello, world!\n") } func main() { http.HandleFunc("/hello", HelloServer) err := http.ListenAndServe(":12345", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } ``` ## func [ListenAndServeTLS](https://github.com/golang/go/blob/master/src/net/http/server.go#L1809 "View Source") ``` func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error ``` ListenAndServeTLS函數和ListenAndServe函數的行為基本一致,除了它期望HTTPS連接之外。此外,必須提供證書文件和對應的私鑰文件。如果證書是由權威機構簽發的,certFile參數必須是順序串聯的服務端證書和CA證書。如果srv.Addr為空字符串,會使用":https"。 一個簡單的服務端例子: ``` import ( "log" "net/http" ) func handler(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "text/plain") w.Write([]byte("This is an example server.\n")) } func main() { http.HandleFunc("/", handler) log.Printf("About to listen on 10443\. Go to https://127.0.0.1:10443/") err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil) if err != nil { log.Fatal(err) } } ``` 程序員可以使用crypto/tls包的generate_cert.go文件來生成cert.pem和key.pem兩個文件。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看