蒟蒻のgolang(gin从入门到实战看这一篇就够了)

虽然辛苦,但我还是会选择那种滚烫的人生。

加油,各位!

5.9:这篇文章前前后后写了两天,最近也没有很频繁的更新。
为什么不去写springboot or cloud的文章:
感觉两者的文章数量已经过于饱和,现在完全可以享受到前人种树后人乘凉这种更好的状态,但是蒟蒻觉得国内的go社区还是有待完善,为了为go社区的发展尽一份绵薄之力,蒟蒻决定好好写一写go大大小小的文章,即使为了方便别人,也是为了加强记忆毕竟自己也蔡 。当然JAVA或者其中间件的也会写,可能是会面向更基础或者更有趣这两个极端。毕竟,写一些主流的文章没太大的意义。

5.8:这两天蒟蒻把电脑重装了一下,原因很简单。
1.开始不注意文件的放置位置,导致C盘爆满,只剩5G,跑idea够呛。
2.电脑名是中文名,很多中间件只能在阿里云上跑。比如rabbitmq,然而activemq可以正常运行。。VM的跑起来就更卡了。。阿里云8月就到期,所以应该做起自力更生的准备
得莫,现在已经在这里插入图片描述
C盘39G真是舒服啊~
要好好爱惜空间了。
由于自己出路时间不长,前期没意识到文件管理的重要性,所以痛下决心折腾一下电脑。
重装的路对小白来说是坎坷的
C盘进行了格式化,我提前把idea,webstorm的数据存在D,其他编译器没保存,想着反正都没用多少。。
然后就是折腾各种语言的运行环境啊,各个中间件的运行环境。。
虽然自己这些都在最开始接触的时候做过不止一次了,遇到难一点的还是会卡很长时间,这个时候感觉自己心态很好,可能是习惯项目调BUG两小时起步的感觉了吧,做起来都很平静。

大半天左右把前后端运行环境都能跑起来我还是很欣慰的。阿里也很鼓励员工养成爱折腾的习惯。比如初玩linux都会有几次失败这样。
遇到问题切莫急躁,程序员大忌。

虽然这些方面做的很好,但是总体还是有损失的,,比如除了idea,webstorm之前的程序,其他ide都没保存。近期也没打算好高骛远,先学好JAVA。

毕竟在一些springcloud内容方面,比如集群的nacos,分布式交易seata啥的,三个nocos阿里云也运行不起来。。。这种工具问题很难解决(学生机太蔡了)。

然后就是把数据库换回了5X。。还是因为sc有些组件8的环境真的太难了。。。例如上面的三个nacos,,官方文档专门写了8x的注意事项,为了学习路线更平滑,我折腾回了5。顺便吐槽mysql真的是我最不想折腾的工具,8换回5也很艰辛。。8.20的BUG也巨多,经常上午好好的下午搞事情,redis的开箱即用真的太好了。。

5.9:
那么开始gin系列的学习。

熟悉一门不是很复杂的框架JAVA就算了 ,看官方文档无疑是个好方法,贴一下gin的文档,貌似有面向中国区的,所以直接可以访问,很友好。
gin
1h内差不多可以通读一遍。

在这里插入图片描述
如果看到这张图,能让你产生xcd的话,那么你已经入门了

所以对着官方文档来:

安装gin

go get -u github.com/gin-gonic/gin

引入

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

接下来就直接在goland可以开一个project来写测试代码了

package main

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

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	// GET:请求方式;/hello:请求的路径
	// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数
	r.GET("/hello", func(c *gin.Context) {
		// c.JSON:返回JSON格式的数据
		c.JSON(200, gin.H{
			"message": "Hello world!",
		})
	})

不出所料各位看到了Hello world的JSON数据。注释解释的差不多了,,接下来对比spring家的乱七八糟 的反射,你应该感叹gin多么友好。。有手就行,而且gin的crud真的是爽到爆。。。体验舒适度大概和人人开源的逆向工程差不多~
路由(Route)
路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS,还有Any,可匹配以上任意类型的请求。

Any基本上可以囊括所有路由,但就像restful开发风格一样,很多就是coder前辈们约定俗成的规则,所以其他的也会用。

// 无参数
r.GET("/", func(c *gin.Context) {
	c.String(http.StatusOK, "Who are you?")
})

直接访问localhost:xxxx/可以看到输出了吧!

curl http://localhost:9999/
Who are you?

有时候我们需要动态的路由,如 /user/:name,通过调用不同的 url 来传入不同的 name。/user/:name/role, 代表可选。
一般来说,就是你随便起的变量名,前面加个:你就可以随心所欲的赋值访问:

http://localhost:9999/user/hhhhhh
Hello hhhhhh

获取Query参数

// 匹配users?name=xxx&role=xxx,role可选
r.GET("/users", func(c *gin.Context) {
	name := c.Query("name")
	role := c.DefaultQuery("role", "teacher")
	c.String(http.StatusOK, "%s is a %s", name, role)
})
curl "http://localhost:9999/users?name=Tom&role=student"
Tom is a student

Query:url上你写的值,不写会为空而不是default值
DefaultQuery:默认访问这个值。

获取POST参数

// POST
r.POST("/form", func(c *gin.Context) {
	username := c.PostForm("username")
	password := c.DefaultPostForm("password", "000000") // 可设置默认值

	c.JSON(http.StatusOK, gin.H{
		"username": username,
		"password": password,
	})
})
 curl http://localhost:9999/form  -X POST -d 'username=qqqq&password=1234'
{"password":"1234","username":"qqqq"}

Query和POST混合参数

// GET 和 POST 混合
r.POST("/posts", func(c *gin.Context) {
	id := c.Query("id")
	page := c.DefaultQuery("page", "0")
	username := c.PostForm("username")
	password := c.DefaultPostForm("username", "000000") // 可设置默认值

	c.JSON(http.StatusOK, gin.H{
		"id":       id,
		"page":     page,
		"username": username,
		"password": password,
	})
})

Map参数(字典参数)

r.POST("/post", func(c *gin.Context) {
	ids := c.QueryMap("ids")
	names := c.PostFormMap("names")

	c.JSON(http.StatusOK, gin.H{
		"ids":   ids,
		"names": names,
	})
})

重定向(Redirect)

r.GET("/redirect", func(c *gin.Context) {
    c.Redirect(http.StatusMovedPermanently, "/index")
})

r.GET("/goindex", func(c *gin.Context) {
	c.Request.URL.Path = "/"
	r.HandleContext(c)
})
 curl -i http://localhost:9999/redirect
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=utf-8
Location: /
Date: Thu, 08 Aug 2019 17:22:14 GMT
Content-Length: 36

<a href="/">Moved Permanently</a>.

$ curl "http://localhost:9999/goindex"
Who are you?

go的重定向貌似有两种,学j2ee的肯定都知道重定向和转发的区别,但是gin这边好像是都叫做重定向,只不过适应不同业务这样,蒟蒻自己的理解,没有过分深究,知道的大佬可以提醒一下。

分组路由(Grouping Routes)
如果有一组路由,前缀都是/api/v1开头,是否每个路由都需要加上/api/v1这个前缀呢?答案是不需要,分组路由可以解决这个问题。利用分组路由还可以更好地实现权限控制,例如将需要登录鉴权的路由放到同一分组中去,简化权限控制。

// group routes 分组路由
defaultHandler := func(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"path": c.FullPath(),
	})
}
// group: v1
v1 := r.Group("/v1")
{
	v1.GET("/posts", defaultHandler)
	v1.GET("/series", defaultHandler)
}
// group: v2
v2 := r.Group("/v2")
{
	v2.GET("/posts", defaultHandler)
	v2.GET("/series", defaultHandler)
}

上传文件
单个文件

r.POST("/upload1", func(c *gin.Context) {
	file, _ := c.FormFile("file")
	// c.SaveUploadedFile(file, dst)
	c.String(http.StatusOK, "%s uploaded!", file.Filename)
})

多个文件

r.POST("/upload2", func(c *gin.Context) {
	// Multipart form
	form, _ := c.MultipartForm()
	files := form.File["upload[]"]

	for _, file := range files {
		log.Println(file.Filename)
		// c.SaveUploadedFile(file, dst)
	}
	c.String(http.StatusOK, "%d files uploaded!", len(files))
})

HTML模板(Template)

type student struct {
	Name string
	Age  int8
}

r.LoadHTMLGlob("templates/*")

stu1 := &student{Name: "Geektutu", Age: 20}
stu2 := &student{Name: "Jack", Age: 22}
r.GET("/arr", func(c *gin.Context) {
	c.HTML(http.StatusOK, "arr.tmpl", gin.H{
		"title":  "Gin",
		"stuArr": [2]*student{stu1, stu2},
	})
})
<!-- templates/arr.tmpl -->
<html>
<body>
    <p>hello, {{.title}}</p>
    {{range $index, $ele := .stuArr }}
    <p>{{ $index }}: {{ $ele.Name }} is {{ $ele.Age }} years old</p>
    {{ end }}
</body>
</html>
$ curl http://localhost:9999/arr

<html>
<body>
    <p>hello, Gin</p>
    <p>0: Geektutu is 20 years old</p>
    <p>1: Jack is 22 years old</p>
</body>
</html>

Gin默认使用模板Go语言标准库的模板text/template和html/template,语法与标准库一致,支持各种复杂场景的渲染。

中间件

// 作用于全局
r.Use(gin.Logger())
r.Use(gin.Recovery())

// 作用于单个路由
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

// 作用于某个组
authorized := r.Group("/")
authorized.Use(AuthRequired())
{
	authorized.POST("/login", loginEndpoint)
	authorized.POST("/submit", submitEndpoint)

自定义中间件

func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()
		// 给Context实例设置一个值
		c.Set("geektutu", "1111")
		// 请求前
		c.Next()
		// 请求后
		latency := time.Since(t)
		log.Print(latency)
	}
}

热加载调试 Hot Reload
Python 的 Flask框架,有 debug 模式,启动时传入 debug=True 就可以热加载(Hot Reload, Live Reload)了。即更改源码,保存后,自动触发更新,浏览器上刷新即可。免去了杀进程、重新启动之苦。

Gin 原生不支持,但有很多额外的库可以支持。例如

github.com/codegangsta/gin
github.com/pilu/fresh

go get -v -u github.com/pilu/fresh

安装好后,只需要将go run main.go命令换成fresh即可。每次更改源文件,代码将自动重新编译(Auto Compile)。

gin的入门就到这里了,下章讲讲gorm,也是超好用的go crud工具!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值