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())
相关文章
相关标签/搜索