Golang中http包的具體使用
Go語言內(nèi)置的net/http包十分優(yōu)秀,提供了http客戶端和服務(wù)器的實現(xiàn)。
超文本傳輸協(xié)議(HTTP,HyperText Transfer Protocol)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)傳輸協(xié)議,所有的www文件都必須遵循這個標準。設(shè)計HTTP最初的目的是為了提供一種發(fā)布和接收HTML頁面的方法。
一. HTTP客戶端
基本的HTTP/HTTPS請求Get,Head,Post和PostForm函數(shù)發(fā)出HTTP/HTTPS請求。
resp, err := http.Get("http://example.com")
//...
resp, err = http.Post("http://example.com", "image/jpeg", &buf)
//...
resp, err = http.PostForm("http://example.com", url.Values{"key": {"value"}, "id": {"123"}})程序在使用完response后必須關(guān)閉回復(fù)的主體。
package main
import (
"io/ioutil"
"log"
"net/http"
)
func main() {
resp, err := http.Get("http://example.com")
if err != nil {
log.Println("http get fail")
return
}
//關(guān)閉回復(fù)主體
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
//...
}1.1 Get請求
函數(shù)簽名:
func Get(url string) (resp *Response, err error)
Get向指定的URL發(fā)出Get請求,如果回應(yīng)的狀態(tài)碼如下,Get會調(diào)用c.CheckRedirect后執(zhí)行重定向。
- 301(Moved Permanently)
- 302(Found)
- 303(See Other)
- 307(Temporary Redirect)
如果c.CheckRedirect執(zhí)行失敗或存在HTTP協(xié)議錯誤時,本方法返回錯誤。如果回應(yīng)的狀態(tài)碼不是2xx,本方法并不會返回錯誤。如果返回值err為nil,resp.Body總是非nil的,調(diào)用者應(yīng)該在讀取完resp.Body后關(guān)閉它。
Get是對DefaultClient的Get方法的包裝。
1.2 post和get示例服務(wù)端代碼
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func getHandleFunc(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
data := r.URL.Query() //獲得get方法的參數(shù)
fmt.Println(data.Get("name"))
fmt.Println(data.Get("age"))
answer := `{"status":"ok"}`
w.Write([]byte(answer))
}
func postHandleFunc(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
//請求數(shù)據(jù)類型是application/json
b, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println("read request body fail ", err)
return
}
fmt.Println(string(b))
answer := `{"statue":"ok"}`
w.Write([]byte(answer))
}
func handleFunc(w http.ResponseWriter, r *http.Request) {
fmt.Println("get a link....")
switch r.Method {
case http.MethodGet:
http.HandleFunc("/get", getHandleFunc)
case http.MethodPost:
http.HandleFunc("/post", postHandleFunc)
}
}
func main() {
http.HandleFunc("/", handleFunc)
err := http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Println("http server fail ", err)
return
}
}1.3 get方法示例
不帶參數(shù)客戶端
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
resp, err := http.Get("https://www.baidu.com")
if err != nil {
log.Println("http get fail ", err)
return
}
//關(guān)閉回復(fù)主體
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("read resp body fail ", err)
return
}
fmt.Print(string(body))
}帶參數(shù)客戶端
關(guān)于Get請求帶參數(shù)需要使用Go語言內(nèi)置的net/url標準庫來處理。
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
apiUrl := "http://127.0.0.1:9090/get"
//URL參數(shù)
data := url.Values{}
data.Set("name", "張三")
data.Set("age", "20")
//URL參數(shù)需要編碼,因為有的特殊字符被賦予了特殊含義
u, err := url.ParseRequestURI(apiUrl)
if err != nil {
fmt.Println("url parse fail ", err)
}
u.RawQuery = data.Encode() //url encode
fmt.Println(u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Printf("url %v get fail %v", u.String(), err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("read body fail ", err)
return
}
fmt.Println(string(b))
}1.4 post請求
函數(shù)簽名:
func Post(url string, bodyType string, body io.Reader) (resp *Response, err error)
Post向指定的URL發(fā)送一個POST請求。bodyType為POST的數(shù)據(jù)類型,Body為POST數(shù)據(jù),作為請求的主體。如果參數(shù)body實現(xiàn)了io.Closer接口,它會在發(fā)送請求后被關(guān)閉。調(diào)用者有責任在讀取完返回值resp的主體后關(guān)閉它。
Post是對包變量DefaultClient的Post方法的包裝。
1.5 post示例
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
apiUrl := "http://127.0.0.1:9090/post"
//表單數(shù)據(jù)
contenttype := "application/json"
data := `{"name":"張三", "age":18}`
resp, err := http.Post(apiUrl, contenttype, strings.NewReader(data))
if err != nil {
fmt.Printf("url : %v post fail err : %v\n", apiUrl, err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("read body err ", err)
return
}
fmt.Println(string(b))
}
1.6 自定義Client
要管理HTTP客戶端頭域,重定向和其它策略,創(chuàng)建一個client:
type Client struct {
// Transport指定執(zhí)行獨立、單次HTTP請求的機制。
// 如果Transport為nil,則使用DefaultTransport。
Transport RoundTripper
// CheckRedirect指定處理重定向的策略。
// 如果CheckRedirect不為nil,客戶端會在執(zhí)行重定向之前調(diào)用本函數(shù)字段。
// 參數(shù)req和via是將要執(zhí)行的請求和已經(jīng)執(zhí)行的請求(切片,越新的請求越靠后)。
// 如果CheckRedirect返回一個錯誤,本類型的Get方法不會發(fā)送請求req,
// 而是返回之前得到的最后一個回復(fù)和該錯誤。(包裝進url.Error類型里)
//
// 如果CheckRedirect為nil,會采用默認策略:連續(xù)10此請求后停止。
CheckRedirect func(req *Request, via []*Request) error
// Jar指定cookie管理器。
// 如果Jar為nil,請求中不會發(fā)送cookie,回復(fù)中的cookie會被忽略。
Jar CookieJar
// Timeout指定本類型的值執(zhí)行請求的時間限制。
// 該超時限制包括連接時間、重定向和讀取回復(fù)主體的時間。
// 計時器會在Head、Get、Post或Do方法返回后繼續(xù)運作并在超時后中斷回復(fù)主體的讀取。
//
// Timeout為零值表示不設(shè)置超時。
//
// Client實例的Transport字段必須支持CancelRequest方法,
// 否則Client會在試圖用Head、Get、Post或Do方法執(zhí)行請求時返回錯誤。
// 本類型的Transport字段默認值(DefaultTransport)支持CancelRequest方法。
Timeout time.Duration
}Client類型代表HTTP客戶端。它的零值(DefaultClient)是一個可用的使用DefaultTransport的客戶端。
Client的Transport字段一般會含有內(nèi)部狀態(tài)(緩存TCP連接),因此Client類型值應(yīng)盡量被重用而不是每次需要都創(chuàng)建新的。Client類型值可以安全的被多個go程同時使用。
Client類型的層次比RoundTripper接口(如Transport)高,還會管理HTTP的cookie和重定向等細節(jié)。
//設(shè)置重定向
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)
//...1.7 自定義Transport
go語言中的http.transport是一個高性能的http客戶端庫,它提供了連接池、重試、超時控制等功能,可以方便地進行 http 請求。
要管理代理,TLS配置,keep-alive,壓縮和其它設(shè)置,可以創(chuàng)建一個Transport,對應(yīng)Client的Transport字段。
type Transport struct {
// Proxy指定一個對給定請求返回代理的函數(shù)。
// 如果該函數(shù)返回了非nil的錯誤值,請求的執(zhí)行就會中斷并返回該錯誤。
// 如果Proxy為nil或返回nil的*URL置,將不使用代理。
Proxy func(*Request) (*url.URL, error)
// Dial指定創(chuàng)建TCP連接的撥號函數(shù)。如果Dial為nil,會使用net.Dial。
Dial func(network, addr string) (net.Conn, error)
// TLSClientConfig指定用于tls.Client的TLS配置信息。
// 如果該字段為nil,會使用默認的配置信息。
TLSClientConfig *tls.Config
// TLSHandshakeTimeout指定等待TLS握手完成的最長時間。零值表示不設(shè)置超時。
TLSHandshakeTimeout time.Duration
// 如果DisableKeepAlives為真,會禁止不同HTTP請求之間TCP連接的重用。
DisableKeepAlives bool
// 如果DisableCompression為真,會禁止Transport在請求中沒有Accept-Encoding頭時,
// 主動添加"Accept-Encoding: gzip"頭,以獲取壓縮數(shù)據(jù)。
// 如果Transport自己請求gzip并得到了壓縮后的回復(fù),它會主動解壓縮回復(fù)的主體。
// 但如果用戶顯式的請求gzip壓縮數(shù)據(jù),Transport是不會主動解壓縮的。
DisableCompression bool
// 如果MaxIdleConnsPerHost!=0,會控制每個主機下的最大閑置連接。
// 如果MaxIdleConnsPerHost==0,會使用DefaultMaxIdleConnsPerHost。
MaxIdleConnsPerHost int
// ResponseHeaderTimeout指定在發(fā)送完請求(包括其可能的主體)之后,
// 等待接收服務(wù)端的回復(fù)的頭域的最大時間。零值表示不設(shè)置超時。
// 該時間不包括獲取回復(fù)主體的時間。
ResponseHeaderTimeout time.Duration
// 內(nèi)含隱藏或非導(dǎo)出字段
} tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: pool,
},
DisableCompression: true,
}
client := &http.Client{
Transport: tr,
}
resp, err := client.Get("http://example.com")
//...二. 服務(wù)端
2.1 默認server
ListenAndServer使用指定的監(jiān)聽地址和處理器啟動一個HTTP服務(wù)端。處理器參數(shù)通常是nil,這表示采用包變量DefaultServeMux作為處理器。
Handle和HandleFunc函數(shù)可以向DefaultServeMux添加處理器。
http.Handle("/foo", fooHandler)
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))2.2 示例
package main
import (
"fmt"
"net/http"
)
func sayHello(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Fprintln(w, "hello 張三")
}
func main() {
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("http server fail, err ", err)
return
}
}2.3 自定義Server
type Server struct {
Addr string // 監(jiān)聽的TCP地址,如果為空字符串會使用":http"
Handler Handler // 調(diào)用的處理器,如為nil會調(diào)用http.DefaultServeMux
ReadTimeout time.Duration // 請求的讀取操作在超時前的最大持續(xù)時間
WriteTimeout time.Duration // 回復(fù)的寫入操作在超時前的最大持續(xù)時間
MaxHeaderBytes int // 請求的頭域最大長度,如為0則用DefaultMaxHeaderBytes
TLSConfig *tls.Config // 可選的TLS配置,用于ListenAndServeTLS方法
// TLSNextProto(可選地)指定一個函數(shù)來在一個NPN型協(xié)議升級出現(xiàn)時接管TLS連接的所有權(quán)。
// 映射的鍵為商談的協(xié)議名;映射的值為函數(shù),該函數(shù)的Handler參數(shù)應(yīng)處理HTTP請求,
// 并且初始化Handler.ServeHTTP的*Request參數(shù)的TLS和RemoteAddr字段(如果未設(shè)置)。
// 連接在函數(shù)返回時會自動關(guān)閉。
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
// ConnState字段指定一個可選的回調(diào)函數(shù),該函數(shù)會在一個與客戶端的連接改變狀態(tài)時被調(diào)用。
// 參見ConnState類型和相關(guān)常數(shù)獲取細節(jié)。
ConnState func(net.Conn, ConnState)
// ErrorLog指定一個可選的日志記錄器,用于記錄接收連接時的錯誤和處理器不正常的行為。
// 如果本字段為nil,日志會通過log包的標準日志記錄器寫入os.Stderr。
ErrorLog *log.Logger
// 內(nèi)含隱藏或非導(dǎo)出字段
}要管理服務(wù)端的行為,可以創(chuàng)建一個自定義的Server:
s := &http.Server{
Addr: ":8080",
Handler: myHander,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}到此這篇關(guān)于Golang中http包的具體使用的文章就介紹到這了,更多相關(guān)Golang http包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

