Go語言標準庫之net_http

[TOC] 更新、更全的《Go從入門到放棄》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-mxrjjcnn-hn.htmlhtml

<p>Go語言內置的<code>net/http</code>包十分的優秀,提供了HTTP客戶端和服務端的實現。</p>python

1、net/http介紹

<p>Go語言內置的<code>net/http</code>包提供了HTTP客戶端和服務端的實現。</p>json

1.1 HTTP協議

<p>超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最爲普遍的一種網絡傳輸協議,全部的WWW文件都必須遵照這個標準。設計HTTP最初的目的是爲了提供一種發佈和接收HTML頁面的方法。</p>api

2、HTTP客戶端

2.1 基本的HTTP/HTTPS請求

<p>Get、Head、Post和PostForm函數發出HTTP/HTTPS請求。</p>瀏覽器

resp, err := http.Get(&quot;http://example.com/&quot;)
...
resp, err := http.Post(&quot;http://example.com/upload&quot;, &quot;image/jpeg&quot;, &amp;buf)
...
resp, err := http.PostForm(&quot;http://example.com/form&quot;,
	url.Values{&quot;key&quot;: {&quot;Value&quot;}, &quot;id&quot;: {&quot;123&quot;}})

<p>程序在使用完response後必須關閉回覆的主體。</p>安全

resp, err := http.Get(&quot;http://example.com/&quot;)
if err != nil {
	// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

2.2 GET請求示例

<p>使用<code>net/http</code>包編寫一個簡單的發送HTTP請求的Client端,代碼以下:</p>服務器

package main

import (
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;net/http&quot;
)

func main() {
	resp, err := http.Get(&quot;https://www.nickchen121.com/&quot;)
	if err != nil {
		fmt.Println(&quot;get failed, err:&quot;, err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(&quot;read from resp.Body failed,err:&quot;, err)
		return
	}
	fmt.Print(string(body))
}

<p>將上面的代碼保存以後編譯成可執行文件,執行以後就能在終端打印<code>nickchen121.com</code>網站首頁的內容了,咱們的瀏覽器其實就是一個發送和接收HTTP協議數據的客戶端,咱們平時經過瀏覽器訪問網頁其實就是從網站的服務器接收HTTP數據,而後瀏覽器會按照HTML、CSS等規則將網頁渲染展現出來。</p>網絡

2.3 帶參數的GET請求示例

<p>關於GET請求的參數須要使用Go語言內置的<code>net/url</code>這個標準庫來處理。</p>app

func main() {
	apiUrl := &quot;http://127.0.0.1:9090/get&quot;
	// URL param
	data := url.Values{}
	data.Set(&quot;name&quot;, &quot;小王子&quot;)
	data.Set(&quot;age&quot;, &quot;18&quot;)
	u, err := url.ParseRequestURI(apiUrl)
	if err != nil {
		fmt.Printf(&quot;parse url requestUrl failed,err:%v\n&quot;, err)
	}
	u.RawQuery = data.Encode() // URL encode
	fmt.Println(u.String())
	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Println(&quot;post failed, err:%v\n&quot;, err)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(&quot;get resp failed,err:%v\n&quot;, err)
		return
	}
	fmt.Println(string(b))
}

<p>對應的Server端HandlerFunc以下:</p>函數

func getHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	data := r.URL.Query()
	fmt.Println(data.Get(&quot;name&quot;))
	fmt.Println(data.Get(&quot;age&quot;))
	answer := `{&quot;status&quot;: &quot;ok&quot;}`
	w.Write([]byte(answer))
}

2.4 Post請求示例

<p>上面演示了使用<code>net/http</code>包發送<code>GET</code>請求的示例,發送<code>POST</code>請求的示例代碼以下:</p>

package main

import (
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;net/http&quot;
	&quot;strings&quot;
)

// net/http post demo

func main() {
	url := &quot;http://127.0.0.1:9090/post&quot;
	// 表單數據
	//contentType := &quot;application/x-www-form-urlencoded&quot;
	//data := &quot;name=小王子&amp;age=18&quot;
	// json
	contentType := &quot;application/json&quot;
	data := `{&quot;name&quot;:&quot;小王子&quot;,&quot;age&quot;:18}`
	resp, err := http.Post(url, contentType, strings.NewReader(data))
	if err != nil {
		fmt.Println(&quot;post failed, err:%v\n&quot;, err)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(&quot;get resp failed,err:%v\n&quot;, err)
		return
	}
	fmt.Println(string(b))
}

<p>對應的Server端HandlerFunc以下:</p>

func postHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	// 1. 請求類型是application/x-www-form-urlencoded時解析form數據
	r.ParseForm()
	fmt.Println(r.PostForm) // 打印form數據
	fmt.Println(r.PostForm.Get(&quot;name&quot;), r.PostForm.Get(&quot;age&quot;))
	// 2. 請求類型是application/json時從r.Body讀取數據
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		fmt.Println(&quot;read request.Body failed, err:%v\n&quot;, err)
		return
	}
	fmt.Println(string(b))
	answer := `{&quot;status&quot;: &quot;ok&quot;}`
	w.Write([]byte(answer))
}

2.5 自定義Client

<p>要管理HTTP客戶端的頭域、重定向策略和其餘設置,建立一個Client:</p>

client := &amp;http.Client{
	CheckRedirect: redirectPolicyFunc,
}
resp, err := client.Get(&quot;http://example.com&quot;)
// ...
req, err := http.NewRequest(&quot;GET&quot;, &quot;http://example.com&quot;, nil)
// ...
req.Header.Add(&quot;If-None-Match&quot;, `W/&quot;wyzzy&quot;`)
resp, err := client.Do(req)
// ...

2.6 自定義Transport

<p>要管理代理、TLS配置、keep-alive、壓縮和其餘設置,建立一個Transport:</p>

tr := &amp;http.Transport{
	TLSClientConfig:    &amp;tls.Config{RootCAs: pool},
	DisableCompression: true,
}
client := &amp;http.Client{Transport: tr}
resp, err := client.Get(&quot;https://example.com&quot;)

<p>Client和Transport類型均可以安全的被多個go程同時使用。出於效率考慮,應該一次創建、儘可能重用。</p>

3、服務端

3.1 默認的Server

<p>ListenAndServe使用指定的監聽地址和處理器啓動一個HTTP服務端。處理器參數一般是nil,這表示採用包變量DefaultServeMux做爲處理器。</p>

<p>Handle和HandleFunc函數能夠向DefaultServeMux添加處理器。</p>

http.Handle(&quot;/foo&quot;, fooHandler)
http.HandleFunc(&quot;/bar&quot;, func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, &quot;Hello, %q&quot;, html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))

3.2 默認的Server示例

<p>使用Go語言中的<code>net/http</code>包來編寫一個簡單的接收HTTP請求的Server端示例,<code>net/http</code>包是對net包的進一步封裝,專門用來處理HTTP協議的數據。具體的代碼以下:</p>

// http server

func sayHello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, &quot;Hello 沙河!&quot;)
}

func main() {
	http.HandleFunc(&quot;/&quot;, sayHello)
	err := http.ListenAndServe(&quot;:9090&quot;, nil)
	if err != nil {
		fmt.Printf(&quot;http server failed, err:%v\n&quot;, err)
		return
	}
}

<p>將上面的代碼編譯以後執行,打開你電腦上的瀏覽器在地址欄輸入<code>127.0.0.1:9090</code>回車,此時就可以看到以下頁面了。 <img src="http://www.chenyoude.com/go/hello.png?x-oss-process=style/watermark" alt="hello.png"/></p>

3.3 自定義Server

<p>要管理服務端的行爲,能夠建立一個自定義的Server:</p>

s := &amp;http.Server{
	Addr:           &quot;:8080&quot;,
	Handler:        myHandler,
	ReadTimeout:    10 * time.Second,
	WriteTimeout:   10 * time.Second,
	MaxHeaderBytes: 1 &lt;&lt; 20,
}
log.Fatal(s.ListenAndServe())
相關文章
相關標籤/搜索