前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

Go HTTP

作者头像
icepy
发布2019-06-24 18:08:18
1.4K0
发布2019-06-24 18:08:18
举报
文章被收录于专栏:子曰五溪

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

简单的Get

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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了。

代码语言:javascript
复制
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的例子。

代码语言:javascript
复制
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端的创建,也很简单。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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方法。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 子曰五溪 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档