Go语言中的HTTP编程

HTTP协议应该大家并不陌生吧,这是现有互联网中应用最为广泛的一种网络协议。
在Go中,标准库中内建提供了net/http包,基本上涵盖了HTTP客户端的具体实现的基本内容,因此,使用net/http包可以很容易的编写HTTP客户端或服务器端的程序。

HTTP客户端

我们在使用Go来建立HTTP客户端之后,无需借助第三方网络通信就可以直接使用HTTP中用得最多的GET和POST方式请求数据。

1.基本用法

1)http.Get()
方法定义:

func (c *Client) Get(url string) (r *Response, err error)

我们要请求一个资源时,只需要调用http.Get()方法即可:

resp, err := http.Get("http://example.com/")
    if err != nil {
    // 处理错误
    return
}
defer resp.Body.close()
io.Copy(os.Stdout, resp.Body)

上面这个例子的功能是对`http://example.com/进行请求,并将请求得到的结果(即网页的内容)打印到标准输出流中。
2)http.Post()
方法定义:

func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error)

函数中的三个参数分别代表的是:请求的目标URL,将要POST数据的资源类型和数据的比特流([]byte格式)。

resp, err := http.Post("http://example.com", "image/jpeg". &imageDataBuf)
if err != nil {
    // 处理错误
    return
}
if resp.StatusCode != http.StatusOK {
    // 处理错误
    return
}

上面这个例子实现了上传一张照片的功能。
3)http.PostForm()
方法定义:

func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)

PostForm向指定的URL发出一个POST请求,url.Values类型的data会被编码为请求的主体。POST数据的类型一般会设为application/x-www-form-urlencoded。如果返回值errnilresp.Body总是非nil的,调用者应该在读取完resp.Body后关闭它。

resp, err := http.PostForm("http://example.com", {"article title"}, "content":{"article body"})
if err != nil {
    // 处理错误
    return
}

上面这个例子模拟了HTML表单提交一篇新文章的功能。
4)http.Head()
方法定义:

func (c *Client) Head(url string) (r *Response, err error)

Head向指定的URL发出一个HEAD请求,如果回应的状态码如下,Head会在调用c.CheckRedirect后执行重定向:

301 (Moved Permanently)
302 (Found)
303 (See Other)
307 (Temporary Redirect)
resp, err := http.Head("http://example.com/")

上面的例子实现了请求一个网站首页的HTTP的Header信息的功能。

2.封装

1)自定义http.Client
前面所介绍的几个函数其实都是在http.DefaultClient函数的基础上进行调用的,比如http.Get()其实是等价于http.DefaultClient.Get()的,
首先我们来看一下http.Client类型的结构:

type Client struct {
    Transport RoundTripper
    CheckRedirect func(req *Request, via []*Request) error
    Jar CookieJar
}

我们来着重介绍一下CheckRedirect函数类型,它指定的是处理重定向的策略,正如前面所说,当使用HTTP ClientGet()或者Head()方法发送HTTP请求时,若响应返回的状态码为30x,HTTPClient会在遵循跳转规则之前先调用这个CheckRedirect函数。
2)http.Transport
在刚才的Client中,第一个成员就是一个http.Transport对象,该对象指定一个HTTP请求时的运行规则。我们分别来看看http.Transport里面有什么对象。

Proxy func(*Request) (*url.URL, error)

该方法接收一个 *Request类型的请求实例作为参数并返回一个最终的HTTP代理。如果Proxy未指定或者返回的*URL为零值,将不会有代理被启用。

Dial func(net, addr string) (c net.Conn, err error)

该函数指定具体的dial()方法来创建TCP连接。

TLSClientConfig *tls.Config

SSL连接专用,TLSClientConfig指定tls.Client所用的TLS配置信息。

DisableKeepAlives bool

是否取消长连接,默认值为false

DisableCompression bool

是否取消压缩(GZip),默认值为false

MaxIdleConnsPerHost int

指定与每个请求的目标主机之间的最大非活跃连接数量(keep-alive)。默认是与DefaultMaxIdleConnsPerHost值相同的。


HTTP服务器端

1.处理HTTP请求

使用net/http包中的http.ListenAndServe()方法,可以在指定的地址进行监听,开启一个HTTP:

func ListenAndServe(addr string, handler Handler) error

该方法用于在指定的TCP网络地址addr进行监听。
具体示例如下:

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.ListenAndServer(":8000", nil))

当然,我们还可以自定义http.Server

s := &http.Server{
    Addr: ":8000",
    Handler: myHandler,
    ReadTimeout: 10 * time.Second,
    WriteTimeout: 10 * time.Secont,
    MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServer())
处理HTTPS请求

net/http包中还提供http.ListenAndServerTLS()的方法,用于处理HTTPS连接请求:

func ListenAndServerTLS(addr string, certFile string, keyFile string, handler Handler) error

开启SSL监听服务也很简单:

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.ListenAndServerTLS(":10413", "cert.pem", "key.pem", nil))

或者是对其进行自定义:

s := &http.Server{
    Addr: ":10413",
    Handler: myHandler,
    ReadTimeout: 10 * time.Second,
    WriteTimeout: 10 * time.Secont,
    MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServerTLS("cert.pem", "key.pem"))

以上是关于HTTP的简单介绍,接下来,我们将讲解RPC的有关内容,敬请期待。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容