zoukankan      html  css  js  c++  java
  • Go组件学习——Web框架Gin

    以前学Java的时候,和Spring全家桶打好关系就行了,从Spring、Spring MVC到SpringBoot,一脉相承。

    对于一个Web项目,使用Spring MVC,就可以基于MVC的思想开发项目了,不管是应对前后端分离还是不分离的场景,你都可以轻松驾驭。因为你只要知道,你用的是一个Web开发框架就行了。

    相比于Spring在Java一家独大的局面,Go生态中的Web框架还在百家争鸣的阶段。从今天开始学习一款基于Go语言开发的Web开发框架Gin。

    简介

    Github:https://github.com/gin-gonic/gin

    语言:Go语言

    官网:https://gin-gonic.com/

    环境搭建

    Go版本:1.12.4

    系统:macOS

    依赖管理工具:go mod

    IDE:Goland

    因为我使用了go mod,所以引用gin的依赖算是很方便了。

    如何创建一个go mod管理的新项目以及如何将老项目改造为go mod,可以参见这篇文章:https://juejin.im/post/5c8e503a6fb9a070d878184a,写的很详细了。

    这就是我的go-demo:https://github.com/DMinerJackie/go-demo项目的所有第三方依赖了。

    那么如何添加gin的依赖呢?有以下三种方式

    • 直接新建一个基于gin的example程序文件,然后执行 go build xxx.go或者 go run xxx.go命令,go mod就会自动帮你下载gin依赖并更新go.mod文件。

    • 同上,还是新建一个example程序文件,然后在项目根目录下执行 go mod tidy命令,go mod会帮你安排上。这个命令可以帮助你移除不需要的依赖,并拉取引用你需要的依赖。

    • 在go.mod文件中手动添加依赖类似 github.com/gin-gonic/gin v1.4.0这种。

    几乎不用什么繁琐的步骤,就完成了环境搭建。下面开始写第一个基于Gin的demo

    第一个Demo

    1、新建文件helloworld.go

    package main
    
    import "github.com/gin-gonic/gin"
    
    func main() {
    	r := gin.Default()
    	r.GET("/ping", func(c *gin.Context) {
    		c.JSON(200, gin.H{
    			"message": "pong",
    		})
    	})
    	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
    }
    

      

    2、点击执行该程序

    从控制台程序可以看出服务已经启动,并且开始监听8080端口

    3、访问接口

    接下来我们在浏览器输入localhost:8080/ping即可看到程序返回的结果

    一个极简的Web服务器就这样搭建完成并对外访问了。

    上面的代码中

    通过 r:=gin.Default()声明一个gin的引擎,后续的操作都是基于这个引擎的。

    通过 r.GET申明一个可以访问的路由,定义的HTTP请求方式为GET请求。同时定义了请求后对应的处理方式,即一个闭包函数声明以JSON格式返回的键值对。

    通过 r.Run()监听指定端口并启动服务

    其他Demo

    1、渲染HTML

    虽然现在很多都倡导并实行前后端分离了,即后端只提供HTTP接口,前端负责调用HTTP接口以及页面渲染。

    但还是有前后端揉在一起的使用场景,gin就提供了这种能力。

    具体的做法是提供一个HTML模板,服务端将得到的数据填充到模板中实现页面的渲染。

    import (
    	"github.com/gin-gonic/gin"
    	"net/http"
    )
    
    func main() {
    	router := gin.Default()
    	router.LoadHTMLGlob("main/src/gin-example/examples/templates/**/*")
    	router.GET("/posts/index", func(c *gin.Context) {
    		c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
    			"title": "Posts",
    		})
    	})
    	router.GET("/users/index", func(c *gin.Context) {
    		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
    			"title": "Users",
    		})
    	})
    	router.Run(":8080")
    }
    

      

    index.tmpl

    {{ define "posts/index.tmpl" }}
    <html><h1>
    	{{ .title }}
    </h1>
    <p>Using posts/index.tmpl</p>
    </html>
    {{ end }}
    

      

    user.tmpl

    {{ define "users/index.tmpl" }}
    <html><h1>
    	{{ .title }}
    </h1>
    <p>Using users/index.tmpl</p>
    </html>
    {{ end }}
    

      

    对应的HTML模板文件目录结构如下

    代码部分

    router.LoadHTMLGlob用于指明HTML模板文件的路径

    router.GET同上,定义访问路由和返回结果,不同于第一个Demo的是,这里有赋值填充的过程,比如

    c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
    			"title": "Posts",
    		})
    

      

    将index.tmpl中定义的 .title替换为"Posts"

    执行结果如下

    2、PureJSON

    func main() {
    	r := gin.Default()
    	
    	// 提供 unicode 实体
    	r.GET("/json", func(c *gin.Context) {
    		c.JSON(200, gin.H{
    			"html": "<b>Hello, 世界!</b>",
    		})
    	})
    	
    	// 提供字面字符
    	r.GET("/purejson", func(c *gin.Context) {
    		c.PureJSON(200, gin.H{
    			"html": "<b>Hello, 世界!</b>",
    		})
    	})
    	
    	// 监听并在 0.0.0.0:8080 上启动服务
    	r.Run(":8080")
    }
    

      

    这里两个GET方法唯一不同的就是要渲染的内容一个使用JSON()方法一个使用PureJSON()方法。

    启动程序后,我们看下访问结果有什么不同

    可以看出JSON()渲染的会有中文以及标签转为unicode编码,但是使用PureJSON()渲染就是原样输出(我的浏览器装了插件,会自动解码,所以不点击右边的”RAW“两个接口返回的结果是一样的)。

    这个问题,本周我们服务端在和客户端对接的时候还遇到了,因为框架返回的JSON串就是经过编码的,但是单独请求放到浏览器是没有问题的,客户端收到的却是经过编码的,最后排查发现是浏览器插件解码了。

    3、渲染多种数据交换格式的数据

    gin支持渲染XML、JSON、YAML和ProtoBuf等多种数据格式

    import (
    	"github.com/gin-gonic/gin"
    	"github.com/gin-gonic/gin/testdata/protoexample"
    	"net/http"
    )
    
    func main() {
    	r := gin.Default()
    
    	// gin.H 是 map[string]interface{} 的一种快捷方式
    	r.GET("/someJSON", func(c *gin.Context) {
    		c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    	})
    
    	r.GET("/moreJSON", func(c *gin.Context) {
    		// 你也可以使用一个结构体
    		var msg struct {
    			Name    string `json:"user"`
    			Message string
    			Number  int
    		}
    		msg.Name = "Lena"
    		msg.Message = "hey"
    		msg.Number = 123
    		// 注意 msg.Name 在 JSON 中变成了 "user"
    		// 将输出:{"user": "Lena", "Message": "hey", "Number": 123}
    		c.JSON(http.StatusOK, msg)
    	})
    
    	r.GET("/someXML", func(c *gin.Context) {
    		c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    	})
    
    	r.GET("/someYAML", func(c *gin.Context) {
    		c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    	})
    
    	r.GET("/someProtoBuf", func(c *gin.Context) {
    		reps := []int64{int64(1), int64(2)}
    		label := "test"
    		// protobuf 的具体定义写在 testdata/protoexample 文件中。
    		data := &protoexample.Test{
    			Label: &label,
    			Reps:  reps,
    		}
    		// 请注意,数据在响应中变为二进制数据
    		// 将输出被 protoexample.Test protobuf 序列化了的数据
    		c.ProtoBuf(http.StatusOK, data)
    	})
    
    	// 监听并在 0.0.0.0:8080 上启动服务
    	r.Run(":8080")
    }
    

      

    今天先到这,后面再看看gin的源码。

    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

  • 相关阅读:
    Kafka集群搭建
    Easyui dialog中嵌入iframe
    图表插件Charts.js的使用
    抽象工厂
    工厂方法
    简单工厂模式
    认识Git
    代理模式
    原型设计Axure的基本使用
    MVC Api 的跨项目路由
  • 原文地址:https://www.cnblogs.com/bigdataZJ/p/gin-helloworld.html
Copyright © 2011-2022 走看看