天逸龙 發表於 2019-12-12 21:02:00

Go语言基础之net/http

<h1 class="post-title">&nbsp;</h1>
<div class="post-content">
<p>Go语言内置的<code>net/http</code>包十分的优秀,提供了HTTP客户端和服务端的实现。</p>
<h2 id="autoid-0-0-0">net/http介绍</h2>
<p>Go语言内置的<code>net/http</code>包提供了HTTP客户端和服务端的实现。</p>
<h3 id="autoid-0-1-0">HTTP协议</h3>
<p>超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。</p>
<h2 id="autoid-0-1-1">HTTP客户端</h2>
<h3 id="autoid-0-2-0">基本的HTTP/HTTPS请求</h3>
<p>Get、Head、Post和PostForm函数发出HTTP/HTTPS请求。</p>
<div class="cnblogs_code">
<pre>resp, err := http.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com/</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
...
resp, err :</span>= http.Post(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com/upload</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">image/jpeg</span><span style="color: rgba(128, 0, 0, 1)">"</span>, &amp;<span style="color: rgba(0, 0, 0, 1)">buf)
...
resp, err :</span>= http.PostForm(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com/form</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    url.Values{</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Value</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">"</span>}})</pre>
</div>
<p>&nbsp;</p>
<p>程序在使用完response后必须关闭回复的主体。</p>
<div class="cnblogs_code">
<pre>resp, err := http.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com/</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> handle error</span>
<span style="color: rgba(0, 0, 0, 1)">}
defer resp.Body.Close()
body, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> ioutil.ReadAll(resp.Body)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span></pre>
</div>
<p>&nbsp;</p>
<h3 id="autoid-0-2-1">GET请求示例</h3>
<p>使用<code>net/http</code>包编写一个简单的发送HTTP请求的Client端,代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">package main

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fmt</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">io/ioutil</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net/http</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

func main() {
    resp, err :</span>= http.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://www.liwenzhou.com/</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">get failed, err:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    defer resp.Body.Close()
    body, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> ioutil.ReadAll(resp.Body)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">read from resp.Body failed,err:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Print(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">(body))
}</span></pre>
</div>
<p>&nbsp;</p>
<p>将上面的代码保存之后编译成可执行文件,执行之后就能在终端打印<code>liwenzhou.com</code>网站首页的内容了,我们的浏览器其实就是一个发送和接收HTTP协议数据的客户端,我们平时通过浏览器访问网页其实就是从网站的服务器接收HTTP数据,然后浏览器会按照HTML、CSS等规则将网页渲染展示出来。</p>
<h3 id="autoid-0-2-2">带参数的GET请求示例</h3>
<p>关于GET请求的参数需要使用Go语言内置的<code>net/url</code>这个标准库来处理。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">func main() {
    apiUrl :</span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://127.0.0.1:9090/get</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> URL param</span>
    data :=<span style="color: rgba(0, 0, 0, 1)"> url.Values{}
    data.Set(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">小王子</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    data.Set(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">18</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    u, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> url.ParseRequestURI(apiUrl)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Printf(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">parse url requestUrl failed,err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
    }
    u.RawQuery </span>= data.Encode() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> URL encode</span>
    <span style="color: rgba(0, 0, 255, 1)">fmt</span><span style="color: rgba(0, 0, 0, 1)">.Println(u.String())
    resp, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> http.Get(u.String())
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">post failed, err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    defer resp.Body.Close()
    b, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> ioutil.ReadAll(resp.Body)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">get resp failed,err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">(b))
}</span></pre>
</div>
<p>&nbsp;</p>
<p>对应的Server端HandlerFunc如下:</p>
<div class="cnblogs_code">
<pre>func getHandler(<span style="color: rgba(0, 0, 255, 1)">w</span> http.ResponseWriter, r *<span style="color: rgba(0, 0, 0, 1)">http.Request) {
    defer r.Body.Close()
    data :</span>=<span style="color: rgba(0, 0, 0, 1)"> r.URL.Query()
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(data.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(data.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
    answer :</span>= `{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">status</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}`
    </span><span style="color: rgba(0, 0, 255, 1)">w</span>.Write([]<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">(answer))
}</span></pre>
</div>
<p>&nbsp;</p>
<h3 id="autoid-0-2-3">Post请求示例</h3>
<p>上面演示了使用<code>net/http</code>包发送<code>GET</code>请求的示例,发送<code>POST</code>请求的示例代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">package main

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fmt</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">io/ioutil</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net/http</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">strings</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> net/http post demo</span>
<span style="color: rgba(0, 0, 0, 1)">
func main() {
    url :</span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://127.0.0.1:9090/post</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 表单数据
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">contentType := "application/x-www-form-urlencoded"
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">data := "name=小王子&amp;age=18"
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> json</span>
    contentType := <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">application/json</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    data :</span>= `{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">小王子</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 128, 1)">18</span><span style="color: rgba(0, 0, 0, 1)">}`
    resp, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> http.Post(url, contentType, strings.NewReader(data))
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">post failed, err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    defer resp.Body.Close()
    b, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> ioutil.ReadAll(resp.Body)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">get resp failed,err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">(b))
}</span></pre>
</div>
<p>&nbsp;</p>
<p>对应的Server端HandlerFunc如下:</p>
<div class="cnblogs_code">
<pre>func postHandler(<span style="color: rgba(0, 0, 255, 1)">w</span> http.ResponseWriter, r *<span style="color: rgba(0, 0, 0, 1)">http.Request) {
    defer r.Body.Close()
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1. 请求类型是application/x-www-form-urlencoded时解析form数据</span>
<span style="color: rgba(0, 0, 0, 1)">    r.ParseForm()
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(r.PostForm) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 打印form数据</span>
    <span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(r.PostForm.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>), r.PostForm.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2. 请求类型是application/json时从r.Body读取数据</span>
    b, err :=<span style="color: rgba(0, 0, 0, 1)"> ioutil.ReadAll(r.Body)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">read request.Body failed, err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Println(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">(b))
    answer :</span>= `{<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">status</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}`
    </span><span style="color: rgba(0, 0, 255, 1)">w</span>.Write([]<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">(answer))
}</span></pre>
</div>
<p>&nbsp;</p>
<h3 id="autoid-0-2-4">自定义Client</h3>
<p>要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client:</p>
<div class="cnblogs_code">
<pre>client := &amp;<span style="color: rgba(0, 0, 0, 1)">http.Client{
    CheckRedirect: redirectPolicyFunc,
}
resp, err :</span>= client.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
req, err := http.NewRequest(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://example.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, nil)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
req.Header.Add(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">If-None-Match</span><span style="color: rgba(128, 0, 0, 1)">"</span>, `W/<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">wyzzy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`)
resp, err :</span>=<span style="color: rgba(0, 0, 0, 1)"> client.Do(req)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span></pre>
</div>
<p>&nbsp;</p>
<h3 id="autoid-0-2-5">自定义Transport</h3>
<p>要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">tr</span> := &amp;<span style="color: rgba(0, 0, 0, 1)">http.Transport{
    TLSClientConfig:    </span>&amp;<span style="color: rgba(0, 0, 0, 1)">tls.Config{RootCAs: pool},
    DisableCompression: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
}
client :</span>= &amp;http.Client{Transport: <span style="color: rgba(0, 0, 255, 1)">tr</span><span style="color: rgba(0, 0, 0, 1)">}
resp, err :</span>= client.Get(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://example.com</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</pre>
</div>
<p>&nbsp;</p>
<p>Client和Transport类型都可以安全的被多个goroutine同时使用。出于效率考虑,应该一次建立、尽量重用。</p>
<h2 id="autoid-0-2-6">服务端</h2>
<h3 id="autoid-0-3-0">默认的Server</h3>
<p>ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量DefaultServeMux作为处理器。</p>
<p>Handle和HandleFunc函数可以向DefaultServeMux添加处理器。</p>
<div class="cnblogs_code">
<pre>http.Handle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/foo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, fooHandler)
http.HandleFunc(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/bar</span><span style="color: rgba(128, 0, 0, 1)">"</span>, func(<span style="color: rgba(0, 0, 255, 1)">w</span> http.ResponseWriter, r *<span style="color: rgba(0, 0, 0, 1)">http.Request) {
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Fprintf(<span style="color: rgba(0, 0, 255, 1)">w</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello, %q</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">:8080</span><span style="color: rgba(128, 0, 0, 1)">"</span>, nil))</pre>
</div>
<p>&nbsp;</p>
<h3 id="autoid-0-3-1">默认的Server示例</h3>
<p>使用Go语言中的<code>net/http</code>包来编写一个简单的接收HTTP请求的Server端示例,<code>net/http</code>包是对net包的进一步封装,专门用来处理HTTP协议的数据。具体的代码如下:</p>
<pre class="line-numbers language-go"><code class=" language-go"><span class="token comment">// http server</span></code></pre>
<div class="cnblogs_code">
<pre>func sayHello(<span style="color: rgba(0, 0, 255, 1)">w</span> http.ResponseWriter, r *<span style="color: rgba(0, 0, 0, 1)">http.Request) {
    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Fprintln(<span style="color: rgba(0, 0, 255, 1)">w</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello 沙河!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
}

func main() {
    http.HandleFunc(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, sayHello)
    err :</span>= http.ListenAndServe(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">:9090</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, nil)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Printf(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http server failed, err:%v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, err)
      return
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<p>将上面的代码编译之后执行,打开你电脑上的浏览器在地址栏输入<code>127.0.0.1:9090</code>回车,此时就能够看到如下页面了。<img src="https://www.liwenzhou.com/images/Go/socket/hello.png"></p>
<h3 id="autoid-0-3-2">自定义Server</h3>
<p>要管理服务端的行为,可以创建一个自定义的Server:</p>
<div class="cnblogs_code">
<pre>s := &amp;<span style="color: rgba(0, 0, 0, 1)">http.Server{
    Addr:         </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">:8080</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    Handler:      myHandler,
    ReadTimeout:    </span><span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(0, 0, 255, 1)">time</span><span style="color: rgba(0, 0, 0, 1)">.Second,
    WriteTimeout:   </span><span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(0, 0, 255, 1)">time</span><span style="color: rgba(0, 0, 0, 1)">.Second,
    MaxHeaderBytes: </span><span style="color: rgba(128, 0, 128, 1)">1</span> &lt;&lt; <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">,
}
log.Fatal(s.ListenAndServe())</span></pre>
</div>
<p>&nbsp;</p>
</div><br><br>
来源:https://www.cnblogs.com/wukai66/p/12031603.html
頁: [1]
查看完整版本: Go语言基础之net/http