Skip to content

Latest commit

 

History

History
249 lines (192 loc) · 10.3 KB

5.4.md

File metadata and controls

249 lines (192 loc) · 10.3 KB

go语言web框架——gin

HTTP请求

在上一节中,我们创建了一个简单的Http服务器,通过在浏览器输入http://127.0.0.1:8000/ ,就看到了网页输出的Hello World了。那这个请求是如何发生的呢?下面我们打开Chrome浏览器,使用右键,选择检查,可以调出Chrome的开发者工具。


下面我们选择其中的Network,并且重新刷新一下网页,我们可以看到中间多了两个请求。


其中第一个是获取网页内容的请求,第二个是获取网页图标的请求。我们点击第一个,可以看到访问的请求,以及数据包。


这里可以看到,我们“General”、“Request Headers”、“Response Headers”这三项,其中“General”显示了一些基本的信息,比如说请求的地址“Request URL”,请求的方法“Request Method”,请求的响应码“Status Code”。

其中请求的方法主要包括Get和Post,Get方法就是我们平时查看网页时候使用的方法,它把请求的参数和内容放在网址中,直接就能看到。而POST则是我们登录、上传文件使用的方法,它把请求的参数放在请求头中,需要通过抓包工具才能看到。本教程在接下来的案例中只会使用到GET方法,有关POST的东西读者可以自行查阅相关资料。

响应码代表着服务器返回的状态,比如说:200代表成功,302代表网址跳转,404代表没有找到相应资源,500代表服务器内部的错误。读者可以在相关的百度百科查阅

请求的网址就不用多说了,下面我们看一下请求头(Request Headers)和响应头(Response Headers)。

首先看看请求头,可以通过点击“view source”查看原始的请求头。


可以看到,第一行使用了GET请求,请求网站的“/”地址,使用HTTP1.1版本的协议。接下来的是一些键值对,比如说Host代表请求的服务器地址,User-Agent代表浏览器的版本信息,其他的读者可以自行百度查阅。

接下来,点击“view source”查看原始的响应头。


类比可以看到,第一行返回了HTTP协议的版本,以及响应码200和响应信息OK。接下来的键值对代表了返回的一些基础信息,时间(Date),内容长度(Content-Length),内容的类型(Content-Type)。

使用telnet发送HTTP Get请求

开启Telnet

在了解了HTTP请求,下面使用telnet这个tcp客户端来模拟一下HTTP请求。我们打开dos界面,首先输入“telnet”查看是否开启了这个命令。


Windows默认是禁用telnet的,所以我这里找不到。我们打开控制面板,选择“程序与功能”。


然后选择“启用或关闭Windows功能”。


找到其中的“Telnet客户端”,点击确定开启此功能。


开启之后,我们重新打开dos界面,输入“telnet”回车之后,就可以看到命令生效了。


发送Get请求

我们关闭当前终端,重新打开个dos终端。下面我们要模拟HTTP请求了,首先要运行5.3节的http_server.go,让服务器跑起来。我们连接的是本地的8000端口,先输入

telnet 127.0.0.1 8000

输入之后,就可以看到进入了一个空白窗口。此时摁下ctrl键 + ']' 键进入输入模式,然后再按回车切换到显式输入模式。

此时我们仿照这用Chrome抓下来的数据,输入"GET / HTTP/1.1[回车]Host:localhost[回车回车]"如下,我们就可以看到输出的“Hello World”了。


gin框架学习

了解了Http请求之后,我们再来说说gin这个框架,虽然我们能在go语言提供的API已经能完成一个网页的显示了,但是通过一些框架,我们可以更容易的完成它,缩短开发的时间。go语言的web框架很多,gin是其中一个我觉得比较简单、易用、性能高的go语言web框架,而且在git上比较活跃,目前(2017年3月2日)已有9000多个star数了。

安装

在此之前,我们并没有实战过如何安装go语言的第三方包。

在这里我们需要用到之前下载好的GitHub客户端提供的Git Shell。我们先打开Git Shell,然后输入git命令确定是否能使用git。


这里可以看到输出了git的使用说明。在这里,我们不能直接打开dos窗口,因为它会提示git命令找不到。


下面就是安装过程了,我们使用go get命令,输入go get github.com/gin-gonic/gin即可完成安装。


等待片刻,即可完成安装。

有的时候,我们会依赖到一些访问不到的包,如:“golang.org/x/net/html”,这种情况,你可以去第三方包下载的网站如:https://gopm.io下载第三方包,输入包名,然后手动导入到$GOPATH里面的src中。


gin的Hello Wold

安装好了gin,我们开始先跑一个HelloWorld。

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.String(200, "Hello World")
    })
    r.Run(":8000")
}

运行之后,访问可以看到一些debug信息,比如下面是向“/”发送了两次GET请求。


不过Windows上的显示并不是很友善,如果你在Mac或者Ubuntu下,将看到很友好的Debug信息。


Web路由

Web的路由就是访问不同的网址可以获取不同的结果,相应的,我们在代码中对不同的网址需要用不同的函数来处理。这里的不同的网址指的并不是网址完全不同,而是形式不同,比如说一个查询温度的,我们可以通过city参数来获取不同城市的温度,而不用为每个不同的城市都编写一个函数来查询它的温度。

在gin中,有两种方式获取,一种是queryString,一种是直接在url的path中获取。我们通过一个查询温度的案例来学习一下,代码见下方:

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()

    //通过queryString
    r.GET("/temp", func(c *gin.Context) {
        city := c.DefaultQuery("city", "") //获取city参数,默认为""
        responseTemp(city, c)
    })


    //通过path
    r.GET("/temp2/:city", func(c *gin.Context) {
        city := c.Param("city")
        responseTemp(city, c)
    })

    r.Run(":8000")
}

func responseTemp(city string, c *gin.Context) {
  temps := map[string]string{
    "北京": "23℃",
    "上海": "20℃",
    "哈尔滨": "11℃",
  }

  if temp, ok:= temps[city]; ok {
    c.String(200, "%s的温度是:%s", city, temp)
  } else {
    c.String(200, "没找到%s的温度", city)
  }
}

这两种方式都是可以的,queryString可以通过“ http://localhost:8000/temp?city=北京 ”访问,而path可以通过“ http://localhost:8000/temp2/北京 ”访问。


渲染HTML

HTML渲染是将模板中的变量、表达式等等做替换,然后转换成HTML再给浏览器。

我们先来看一个最简单的模板引擎,下面的HTML模板中引入了一个变量title,我们可以通过传递title参数,然后模板通过解析"{{ }}",并对变量进行替换,然后显示相应的结果。

<html>
    <h1>
        {{ .title }}
    </h1>
</html>

除了变量以外,还有各种表达式(if、for),下面以上面查询天气的接口为例子,先创建一个templates目录,并创建temp.tmpl。


填写我们温度查询的模板。

<html>
    {{if .temp}}
      <h1>{{ .city }}的温度是:{{ .temp }}</h1>
    {{ else }}
      <h1>没有找到{{ .city }}的温度</h1>
    {{ end }}
</html>

编写代码:

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()

    r.LoadHTMLGlob("./templates/*")
    r.GET("/temp/:city", func(c *gin.Context) {
      city := c.Param("city")

      temps := map[string]string{
        "北京": "23℃",
        "上海": "20℃",
        "哈尔滨": "11℃",
      }

      if temp, ok:= temps[city]; ok {
        c.HTML(200, "index.tmpl", gin.H{
            "city": city,
            "temp": temp,
        })
      } else {
        c.HTML(200, "index.tmpl", gin.H{
            "city": city,
        })
      }
    })

    r.Run(":8000")
}

静态文件服务器

除了一些动态资源外,编写网站还需要图片资源,这里我们比如说把静态资源都放在static目录下面。(如果读者没有学习过HTML、CSS、JS的话可以跳过此部分)


我们创建好static下面的css、js目录,然后准备我们的测试文件。

style.css:

body {
  background-color: #eee;
}

main.js:

alert("js 测试");

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>静态文件测试</title>
    <link rel="stylesheet" href="/static/css/style.css">
  </head>
  <body>
    <h1>静态文件测试</h1>
    <script src="/static/js/main.js"></script>
  </body>
</html>

最后使用gin的StaticFS方法就可以构建静态文件系统

r.StaticFS("/static", http.Dir("./static"))

运行程序,可以看到js代码执行后显示出了提示框,以及body的背景也变成了灰色。


链接