Go HTTP

在网络编程里多数情况下,我们都在处理HTTP请求,关于请求协议的部分我推荐阅读《TCP协议》这本书,绝对值得购买。Go语言也提供了一个标准库包net/http,让开发者可以快速的处理HTTP请求,其封装的易用性,足够简单。并且,整个net包里提供了多种多样的处理模块,比如rpc等等。http包提供了HTTP客户端和服务端的实现,这让我想到了Node.js提供的http模块。

简单的Get

response, err := http.Get("http://icepy.me")
if err != nil {   
    // handle error
}
defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(body))

简单的Post

body := "{\"action\":20}"
res, err := http.Post("http://icepy.me", "application/json;charset=utf-8", bytes.NewBuffer([]byte(body)))
if err != nil {
   fmt.Println("Fatal error ", err.Error())
}
defer res.Body.Close()
content, err := ioutil.ReadAll(res.Body)
if err != nil {
   fmt.Println("Fatal error ", err.Error())
}
fmt.Println(string(content))

简单的PostFrom

resp, err := http.PostForm("http://icepy.me",
url.Values{"key": {"Value"}, "id": {"123"}})
if err != nil {// handle error}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {// handle error}
fmt.Println(string(body))

在上述的两个方法中,也就是说Get,Post提供了非常方便的快捷方式来处理,真正的做到了无须关心协议的细节问题,当然如果你想拥有更多的灵活性,那么就要用到http.Client和http.NewRequest了。

v := url.Values{}
v.Set("username", "xxxx")
v.Set("password", "xxxx")
body := ioutil.NopCloser(strings.NewReader(v.Encode()))
client := &http.Client{}
reqest, err := http.NewRequest("POST", "http://icepy.me", body)
if err != nil {
   fmt.Println("Fatal error ", err.Error())
}
reqest.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(reqest)
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
   fmt.Println("Fatal error ", err.Error())
}
fmt.Println(string(content))

再来看一个文件上传的例子,不过我个人更喜欢直接传二进制数据,这个比较简单,可以直接[]byte,稍微复杂一些的就是multipart的例子。

file, err := os.Open(path)
if err != nil {	
    return nil, err
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile(paramName, filepath.Base(path))
if err != nil {	
    return nil, err
}
_, err = io.Copy(part, file)
for key, val := range params {
   _ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {	
    return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Add("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(request)

如果你有细心阅读下,肯定发现了一个使用频率很高的类型url.Values,基本上不管是Get请求的参数还是Post请求的参数,如果你不想自己重复造轮子的话,可以将参数直接.Add在这个对象上,它提供了包括编码的Encode,并且如果你要提交的参数是一个数组的话,也可以很方便的通过循环.Add("arr", arr[i])的方式添加。(额外提一句,因为协议规定的如果是数组,可以如此来描述:“a=1&a=2&a=3”)

上述基本上就是HTTP的Client,接下来要说一说HTTP的Server,基本上也可以预想到,Server端的创建,也很简单。

package main
import (    
"net/http"
)
func SayHello(w http.ResponseWriter, req *http.Request) {
   w.Write([]byte("Hello"))
}
func main() {
   http.HandleFunc("/hello", SayHello)
   http.ListenAndServe(":8001", nil)
}

首先定义路由规则和对应的Handle,其次是调用ListenAndServer来启动一个8001端口,我们也可以直接使用http.Server。

s := &http.Server{    
    Addr: ":8080",   
    Handler: myHandler,    
    ReadTimeout: 10 * time.Second,    
    WriteTimeout: 10 * time.Second,    
    MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServe())
  • 实例化Server
  • 调用Server的ListenAndServe()
  • 调用net.Listen(“tcp”, addr)监听端口
  • 启动一个for循环,在循环体中Accept请求
  • 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()
  • 读取每个请求的内容w, err := c.readRequest()
  • 判断header是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为DefaultServeMux
  • 调用handler的ServeHttp
  • 在这个例子中,下面就进入到DefaultServerMux.ServeHttp
  • 根据request选择handler,并且进入到这个handler的ServeHTTP

不过,对于HTTP Server来说,就要说到如何获取参数的问题了,我们来看一下golang http.request的三个属性Form、PostForm、MultipartForm,简要说明如下,基本上你使用对应的方法,就能获取到相应的参数。

  • Form:存储了post、put和get参数,在使用之前需要调用ParseForm方法。
  • PostForm:存储了post、put参数,在使用之前需要调用ParseForm方法。
  • MultipartForm:存储了包含了文件上传的表单的post参数,在使用前需要调用ParseMultipartForm方法。

本文分享自微信公众号 - 子曰五溪(fed-talk)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • A Guide to Node.js Logging

    当你开始使用 JavaScript 做开发时,你可能学习到的第一件事情就是如何使用 console.log 将内容打印到控制台。如果你搜索如何调试 JavaSc...

    icepy
  • 早读《TypeScript Generics Too Hard?》

    最近在阅读 Redux源码,这才发现它用 TypeScript 重写了,稍微有一些绕脑,因为:

    icepy
  • Debug的那些事儿

    我们写代码的多多少少有一些出错的几率,掌握Debug还是很重要的,记得第一次入行写企业系统时,对此一无所知,后来还是去网路上以及问前辈,我印象中还是在博客园里看...

    icepy
  • reStructuredtext快速入门

    reStructuredText是一种reStructuredText是一种轻量级的文本标记语言,简单易读,所见即所得的文本标记语言。

    用户2936342
  • 加密解密 CTR IGE DH等

    CTR 全称为计数器模式(Counter mode),该模式由 Diffe 和 Hellman 设计。一种分组密码的模式

    solate
  • 碎片化、干货、速成…这类流行词正在让你慢慢变傻

    作者 CDA 数据分析师 生活在这个快捷的时代,很多人都热衷于“快餐式”生活。 于是“碎片化”“干货”“速成”“公开课”等逐渐成为流行热词。 而碎片化学习的...

    CDA数据分析师
  • 因为产品意见不合打架?想多了!

    我发现爆料人非常会炒作,本来就是两个人抢微波炉引起的冲突吧,结果说成程序员与产品经理因为产品意见不合而引起的冲突!

    叫我龙总
  • Spark和RDD究竟该如何理解?

    1.Spark的核心概念是RDD (resilient distributed dataset),指的是一个只读的,可分区的分布式数据集,这个数据集的全部或部分...

    挖掘大数据
  • 是什么让你的电脑越来越慢?(二)

    电脑上除了操作系统本身占用的资源外,剩下的都是应用软件占用。我们都知道,应用软件是需要我们运行了以后,才会占用资源。可是我电脑一开机也没有运行啥软件,怎么就是这...

    简单并不简单
  • 被骂“没前途”,996的程序员做错了什么?

    从吴军的新书,得知有一个37%幸福规则,是科学家经过大量数据分析总结而来的,大意如下:

    一墨编程学习

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动